| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
| |
|
| |
|
|
|
|
|
| |
to be increased.
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
| |
or executable and exit.
|
| |
|
| |
|
| |
|
|
|
|
|
| |
executable's ELF interpreter on standard output and exits.
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
| |
read-only.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
| |
FILENAME' switch.
* Shrinking of the RPATH. The switch `--shrink-rpath' will cause all
directories in the RPATH that don't actually contain libraries
required by the executable to be removed from the RPATH.
* Only grow the front of the executable if needed.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
added the new PT_INTERP segment at the end of the file, which
however makes it (typically) appear right in the middle of the
(uninitialised) data segment. Worse, it wasn't guaranteed that the
new segment was mapped into memory, and the dynamic loader does
expect that. If the segment crossed or started beyond the last page
of the last mapped segment, the program would crash.
The "simple" solution is to add a PT_LOAD segment that maps the
PT_INTERP segment into memory, but that creates a new problem,
namely, that we then have to grow the program header table. Moving
the program header table to the end of the file doesn't work,
unfortunately, due to a bug in the Linux kernel: the address that it
passes to the interpreter is wrong if there are holes or duplicates
in the address space (it passes the base address + the program
header table offset, instead of the virtual address specified in the
PT_PHDR segment) - this is almost always the case due to the
uninitialised part of the data segment which doesn't appear in the
executable.
The real solution used now is to move the entire contents of the
executable one page (4096 bytes), put the new program header table
(and the PT_INTERP segment) in the first page of the file thus
created, add a PT_LOAD segment that starts one page before the
original segments of the executable (typically 0x8047000 and
0x8048000, respectively), and adjust the internal offsets in the ELF
header and program and section headers.
The downside is that it makes all executables 4 KB larger.
|
| |
|
|
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).
|