Subject: Playing with ELF
To: None <netbsd-users@netbsd.org>
From: Quentin Garnier <netbsd@quatriemek.com>
List: netbsd-users
Date: 03/06/2003 06:10:19
Hi,
While working on making OpenGL support with NVidia drivers easy to install
and as transparent as possible, I'm struggling with my lack of knowledge
about ELF internals.
To make a long story short, I want to edit NVidia's libGL.so.1 to add a
dependancy on libpthread.so (for the __error symbol, binary-editing it to
__errno is fine). So I did the following thing, but it doesn't look it's
enough : programs end with SIGILL, which make me think a jump or call
doesn't go where it should.
1. Add a NEEDED entry in .dynamic, and libthread.so.0 to the .dynstr
section.
2. Adjust various offset and sizes in ELF header, program headers, section
headers and .dynamic section (things like INIT and FINI).
3. Adjust symbols table.
4. Adjust relocation tables accordingly to the new offsets.
libGL.so.1 contains the following sections :
[Nr] Name Type Addr Off Size
[ 0] NULL 00000000 000000 000000
[ 1] .hash HASH 00000094 000094 002cc4
[ 2] .dynsym DYNSYM 00002d58 002d58 007280
[ 3] .dynstr STRTAB 00009fd8 009fd8 006850
[ 4] .rel.text REL 00010828 010828 003d00
[ 5] .rel.rodata REL 00014528 014528 001078
[ 6] .rel.data REL 000155a0 0155a0 001710
[ 7] .text PROGBITS 00016cb0 016cb0 02b114
[ 8] .rodata PROGBITS 00041dd0 041dd0 001720
[ 9] .nvid PROGBITS 000434f0 0434f0 000060
[10] .data PROGBITS 00044550 043550 00188c
[11] .got PROGBITS 00045ddc 044ddc 00000c
[12] .dynamic DYNAMIC 00045de8 044de8 000098
[13] .sbss PROGBITS 00045e80 044e98 000000
[14] .bss NOBITS 00045e98 044e98 002380
[15] .comment PROGBITS 00000000 044e98 000802
[16] .note NOTE 00000000 04569a 000334
[17] .shstrtab STRTAB 00000000 0459ce 000093
The string "libpthread.so.8" was added at the end of .dynstr, thus the
offset 0x10818 became 0x10828 and so did the following ones.
The NEEDED entry occupies 8 bytes in .dynamix, therefore following offsets
and addresses were increased by another 8.
.hash uses index of symbol in the symbol table, and therefore doesn't need
any adjustment.
.dynsym was updated as following : if entry.st_value >= 0x10818, add 0x10.
Then if entry.st_value >= 45e08 (that's where the NEEDED entry was added),
add 8. So for symbols >=45e08, a total of 24 was added.
.rel.* were updated in the exact same way, applying on the r_offset field
this time.
.nvid contains an informational build time string.
.got contains a reference to the start of the .dynamic section. I tried
not adjusting and adjusting it with the same end result.
.sbss is empty, .bss doesn't exists in the file, .comment and .note are
informational and .shstrtab contains only the names of the sections so
didn't need to be adjusted.
So, is there something obvious that I am missing ? Would it be possible
that somewhere in .text there is a somewhat direct reference that I would
need to adjust (although I'm pretty sure that's what .rel.text is for) ?
The reason behind this is that if a wrapper library (which contains
nothing but a dependancy on the real libGL and libpthread) is convenient
for binaries linked against libGL, it is not the case for binaries the
dlopen() it (like the Quake series which use a modular renderer). The
latter can work, but not without having to configure it to load the
correct library (which can sometimes mean patching the source).
Thanks in advance for any help on that issue.
--
Quentin Garnier - cube@cubidou.net
"Feels like I'm fiddling while Rome is burning down.
Should I lay my fiddle down and take a rifle from the ground ?"
Leigh Nash/Sixpence None The Richer, Paralyzed, Divine Discontents, 2002.