our own glibc, to change the rpath, and so on. This enable us to
use third-party programs in a pure Nix environment, and to "shrink"
the rpath of Nix-built executables to contain only those directories
that are actually needed (in order to reduce the number of retained
dependencies).
In order to use our own glibc, we have to set the executable's ELF
interpreter field to our glib'c ld-linux.so instead of the typical
/lib/ld-linux.so.2. The name of the interpreter is stored in the
PT_INTERP segment of the executable. A complication is that this
segment is too small to store the path to our ld-linux.so. We
cannot just make this segment bigger, since the segment is actually
mapped into the executable's virtual memory space, so that making it
bigger will move all following segments in memory. That would break
executables, since they are typically not position-independant (they
expect to be loaded at specific addresses in memory).
The solution is to add a *new* segment at the end of the
executable. (The data containing the original PT_INTERP segment
becomes "dead" space within the executable.) This seems to work:
e.g., I've succesfully patched SuSE's /bin/cat.
Something similar could be done for the rpath, although that's a bit
more complicated since the rpath string is stored indirectly (the
PT_DYNAMIC segment merely contains a pointer to a string in the
DT_STRTAB section of the executable, which we cannot grow either, so
we would have to copy it to the end of the file).