How Linux dynamic loaders can be both shared objects and executables

March 15, 2022

I was reading RPATH, or why lld doesn’t work on NixOS (via) and ran across this comment:

[...] And at runtime loader (also known as dynamic linker (its binary name is something like, but despite the .so suffix, it’s an executable (I kid you not, this stuff is indeed this confusing))) loads the executable together with shared libraries required by it. [...]

What's being talked about here is the normal ELF interpreter, and there is a story here about this dual nature and the file extension.

ELF interpreters are typically given a .so extension (they often also have a version number) because they are in fact shared objects, somewhat like other shared libraries. They're loaded by the kernel and invoked in a special way, but that's somewhat of a detail. As a pragmatic matter, it helps if the dynamic linker is an ordinary ELF object that can be built, inspected, and manipulated by general tools that know about ELF objects. For example, if you want your debugger to be able to peer into the very early state of a program before it reaches main(), it helps a lot if the debugger doesn't need an entire separate set of code in order to understand the ELF interpreter, find symbols in it, and so on.

ELF interpreters on Linux are typically executable for two reasons. At the technical level, they can straightforwardly be executable because they are where the kernel will start executing a dynamically linked program. Since the kernel has to find out the ELF interpreter's entry point somehow, it's simplest if the ELF interpreter has the form of a statically linked program (reusing kernel code that the kernel already needs for that job).

At the broad philosophical level, ELF was created or at least soon used to cover both (shared) libraries and executables. Once you're using the same general format for shared objects (even if they're loaded by the kernel) and executables, you practically invite clever people to make polymorphic things that are both shared libraries and executables at once.

(You don't have to make your dynamic loader also work as an executable, and the *BSDs don't seem to do this. A relatively current OpenBSD system doesn't even have an executable (it's mode 444), and on the FreeBSD system I have access to, is executable but dumps core if run directly.)

Written on 15 March 2022.
« Where cut comes into Unix (and a bit on the history of awk)
People might want to think about saving a copy of Go 1.17 »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Tue Mar 15 22:23:03 2022
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.