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.