[obj2yaml] Emit ProgramHeader.Offset
Currently, obj2yaml doesn't emit the offset of program headers, leaving it to yaml2obj to calculate offsets based on `FirstSec` and `LastSec`. This causes an obj2yaml->yaml2obj round trip to often produce an ELF file that is not equivalent to the original, especially since it seems common to have program headers at offset 0 whose first section starts at a higher address. Besides being non-equivalent, the produced ELF files also do not seem to work propery and readelf complains about them. Taking a simple hello world program in C, compiled using either GCC or Clang, the original ELF file has the following program headers (only showing some relevant ones): ``` Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040 0x00000000000002d8 0x00000000000002d8 R 0x8 INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318 0x000000000000001c 0x000000000000001c R 0x1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000630 0x0000000000000630 R 0x1000 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000000161 0x0000000000000161 R E 0x1000 ... Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 03 .init .plt .text .fini ... ``` While this is the result of an obj2yaml->yaml2obj round trip: ``` Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000000 0x0000000000000040 0x0000000000000040 0x0000000000000000 0x0000000000000000 R 0x8 readelf: Error: the PHDR segment is not covered by a LOAD segment INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318 0x000000000000001c 0x000000000000001c R 0x1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000318 0x0000000000000000 0x0000000000000000 0x0000000000000318 0x0000000000000318 R 0x1000 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000000161 0x0000000000000161 R E 0x1000 ... Section to Segment mapping: Segment Sections... 00 01 .interp 02 03 .init .plt .text .fini ... ``` Note that the offset of segment 2 changed from 0x0 to 0x318. This has two effects: - readelf complains "Error: the PHDR segment is not covered by a LOAD segment" since PHDR was originally covered by segment 2 but not anymore; - Segment 2 effectively became empty according to the section to segment mapping. I addition to these, the output doesn't correctly execute anymore, crashing with a "SIGSEGV (Address boundary error)". This patch fixes the difference in program header layout after a round trip by explicitly emitting offsets. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D145555
Loading
Please sign in to comment