-
-
Notifications
You must be signed in to change notification settings - Fork 520
Description
Running patchelf to enlarge my RUNPATH entry causes my section headers to change from this:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298
0000000000000064 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 0000000000400300 00000300
00000000000011b8 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 00000000004014b8 000014b8
0000000000000868 0000000000000000 A 0 0 1
...
To this:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .dynsym DYNSYM 00000000003ffb00 001ffb00
00000000000011b8 0000000000000018 A 2 1 8
[ 2] .dynstr STRTAB 00000000003ff270 00000270
0000000000000890 0000000000000000 A 0 0 8
[ 3] .gnu.hash GNU_HASH 0000000000400cb8 00001cb8
0000000000000064 0000000000000000 A 1 0 8
[ 4] .interp PROGBITS 0000000000400d20 00001d20
000000000000001c 0000000000000000 A 0 0 8
[ 5] .note.ABI-tag NOTE 0000000000400d40 00001d40
0000000000000020 0000000000000000 A 0 0 8
[ 6] .note.gnu.build-i NOTE 0000000000400d60 00001d60
0000000000000024 0000000000000000 A 0 0 8
...
This confuses tools such as strip because they use a header offset of 0 as an error code; here's the relevant function assign_file_positions_for_non_load_sections in elf.c from binutils. Running e.g. gdb --args strip -g my_binary, and setting a breakpoint at that position shows that we get a valid section, but since its filepos is equal to zero, binutils ignores it and continues on, getting confused. Note that even readelf gets a little confused by this, as it doesn't even list the .dynsym segment:
$ readelf -l my_binary
...
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .data.rel.ro .dynamic .got
$ readelf my_patched_binary
...
Section to Segment mapping:
Segment Sections...
00
01
02 .dynstr
03 .gnu.hash .interp .note.ABI-tag .note.gnu.build-id .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
04
05 .interp
06 .eh_frame_hdr
07 .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss
08 .init_array .fini_array .jcr .data.rel.ro .dynamic .got
09 .dynamic
I theorize that if we keep the .interp section at the beginning of the file, we might be able to still use tools such as strip, but I don't actually know. Is there an easy way to permute the order of headers that patchelf outputs? If you can just point me in the direction of how to do this, I can submit a PR.