Currently, eu-readelf is using section headers (in readelf.c:handle_symtab(), it calls gelf_getshdr() for fetching section headers and get related info like section size, type, etc) to find the symbol information and print them. This task will add new options to eu-readelf (-D and --use-dynamic). And this task aims for printing the symbols by lookup through the program headers and the dynamic table. PT_DYNAMIC->DT_* for DT_{GNU_,}HASH, DT_SYMTAB, DT_STRSZ, DT_VERNEED, DT_VERSYM(for version information), etc. previous discussion: https://bugzilla.redhat.com/show_bug.cgi?id=444621
This Bug depends on Bug 28928 because when calling `$ eu-readelf -d --use-dynamic {FILE}` eu-readelf will need the number of dynamic section entris which involves with Bug 28928
commit 369c021c6eedae3665c1dbbaa4fc43afbbb698f4 Author: Di Chen <dichen@redhat.com> Date: Thu Apr 28 19:55:33 2022 +0800 readelf: Support --dynamic with --use-dynamic Currently, eu-readelf is using section headers to dump the dynamic segment information (print_dynamic -> handle_dynamic). This patch adds new options to eu-readelf (-D, --use-dynamic) for (-d, --dynamic). https://sourceware.org/bugzilla/show_bug.cgi?id=28873 Signed-off-by: Di Chen <dichen@redhat.com>
Finished the first part of the whole task, now eu-readelf can dump the dynamic segment information from dynamic program header, i.e. ``` $ ./src/readelf -Dd ~/test/eu-readelf-no-shdr Dynamic segment contains 26 entries: Addr: 0x0000000000474e00 Offset: 0x073e00 Type Value NEEDED Shared library: [libdw.so.1] NEEDED Shared library: [libelf.so.1] NEEDED Shared library: [libc.so.6] INIT 0x0000000000404000 FINI 0x000000000043d4a8 INIT_ARRAY 0x0000000000474df0 INIT_ARRAYSZ 8 (bytes) FINI_ARRAY 0x0000000000474df8 FINI_ARRAYSZ 8 (bytes) GNU_HASH 0x00000000004003a0 STRTAB 0x00000000004016b0 SYMTAB 0x00000000004003f0 STRSZ 3086 (bytes) SYMENT 24 (bytes) DEBUG PLTGOT 0x0000000000475000 PLTRELSZ 4560 (bytes) PLTREL RELA JMPREL 0x00000000004026a0 RELA 0x0000000000402610 RELASZ 144 (bytes) RELAENT 24 (bytes) VERNEED 0x0000000000402450 VERNEEDNUM 3 VERSYM 0x00000000004022be NULL ```
Update: I am working on the second part of the task, make eu-readelf can dump symbol information from dynamic program header, like $ eu-readelf -Ds {FILE}
Created attachment 14600 [details] readelf: display dynamic symtab without section headers ``` # failed to print symtab of a binary which has section headers removed. $ ./src/readelf -s ~/test/a.out # it works with "-D" for a binary which has section headers removed. $ ./src/readelf -Ds ~/test/a.out 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UNDEF 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UNDEF __libc_start_main@GLIBC_2.34 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UNDEF __gmon_start__ ``` It works well for binaries which has SYMTAB section right after STRTAB section. ``` $ readelf -Dd ~/test/a.out Dynamic section at offset 0x2e60 contains 20 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000c (INIT) 0x401000 0x000000000000000d (FINI) 0x401124 0x0000000000000019 (INIT_ARRAY) 0x403e50 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001a (FINI_ARRAY) 0x403e58 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000006ffffef5 (GNU_HASH) 0x4003c0 0x0000000000000005 (STRTAB) 0x400428 0x0000000000000006 (SYMTAB) 0x4003e0 0x000000000000000a (STRSZ) 55 (bytes) 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000015 (DEBUG) 0x0 0x0000000000000007 (RELA) 0x400488 0x0000000000000008 (RELASZ) 48 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x000000006ffffffe (VERNEED) 0x400468 0x000000006fffffff (VERNEEDNUM) 1 0x000000006ffffff0 (VERSYM) 0x400460 0x0000000000000000 (NULL) 0x0 ``` Because I use offset difference between SYMTAB and STRTAB to get the symbol table entry number. ``` size_t syments = ((offs[i_strtab] - offs[i_symtab]) / gelf_fsize(ebl->elf, ELF_T_SYM, 1, EV_CURRENT)); ```
[Follow the last comment] For a binary with SYMTAB STRTAB having different order, like upside down, or having other section in between. eg. ``` $ readelf -Dd /usr/local/go/bin/go Dynamic section at offset 0x9e5220 contains 19 entries: Tag Type Name/Value 0x0000000000000004 (HASH) 0xb3c3c0 0x0000000000000006 (SYMTAB) 0xb3c880 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000005 (STRTAB) 0xb3c660 0x000000000000000a (STRSZ) 531 (bytes) 0x0000000000000007 (RELA) 0xb3bfd8 0x0000000000000008 (RELASZ) 24 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x0000000000000003 (PLTGOT) 0xde5100 0x0000000000000015 (DEBUG) 0x0 0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000006ffffffe (VERNEED) 0xb3c360 0x000000006fffffff (VERNEEDNUM) 2 0x000000006ffffff0 (VERSYM) 0xb3c300 0x0000000000000014 (PLTREL) RELA 0x0000000000000002 (PLTRELSZ) 768 (bytes) 0x0000000000000017 (JMPREL) 0xb3bff0 0x0000000000000000 (NULL) 0x0 ``` It will mess up the syments (symbol table entry number) calculation.