kzinti wrote:
That's very interesting. I didn't know this. I use the section headers to find the symbols in order to apply relocations (my kernel is a relocatable executable aka a shared object / .so). Is there another way to go about relocating my binary?
Well, it's not like that. You have to relocate your binary the same way, it's just the information is in a different format (a more compact and easier to parse format my I add).
1. look for the PT_DYNAMIC table in the program headers
2. dynamic table contains fix sized records (similar to section headers)
3. instead of string comparision (sectionname==".symtab") you simply compare integers (sectiontype==DT_SYMTAB)
4. data relocation info can be found likewise, using DT_RELA. Relocation entry size is stored in DT_RELAENT.
5. function relocation info pointed by DT_JMPREL.
6. this table also lists the needed shared libraries, with DT_NEEDED (see "ldd" output)
This dynamic table is mandatory for relocatable binaries and for binaries that use shared libraries. For full list of available records see:
https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-42444.html Table 13-8.
Now locating relocation info is a bit tricky, because someone misread the original
SCO ELF spec (page 89-90), and Linux kernel is not really compliant. Unfortunately these days GNU ld (
save SPARC port) and LLVM lld developers use the Linux kernel as a reference, therefore now it's perfectly valid to have one relocation table which contains both data and jump relocation records (as the spec mandates), and also to have two seprated relocation tables (as Linux kernel implements). This is highly dependent on linker script defaults now, but you can force one table with a specific linker script. There was an LLVM lld bug about this which I have repoted and which they fixed in recent versions (I love those guys, they really care about the quality of their linker).
If you use the ELF spec literally, you'll have only one table, DT_JMPREL pointing somewhere in the middle of it:
Code:
+---+ start of relocation table, pointed by DT_RELA
| | (each record DT_RELAENT bytes)
| |
+---+ pointed by DT_JMPREL, contains code relocations from now on
| |
+---+ end of table, DT_RELA + DT_RELASZ.
Cheers,
bzt