Skip to content

Commit 8545093

Browse files
committed
[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
1 parent 11b89dd commit 8545093

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

llvm/test/Object/obj2yaml.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,12 +711,14 @@ FileHeader:
711711
# ELF-AVR-NEXT: FirstSec: .text
712712
# ELF-AVR-NEXT: LastSec: .text
713713
# ELF-AVR-NEXT: Align: 0x2
714+
# ELF-AVR-NEXT: Offset: 0x74
714715
# ELF-AVR-NEXT: - Type: PT_LOAD
715716
# ELF-AVR-NEXT: Flags: [ PF_W, PF_R ]
716717
# ELF-AVR-NEXT: FirstSec: .data
717718
# ELF-AVR-NEXT: LastSec: .data
718719
# ELF-AVR-NEXT: VAddr: 0x800060
719720
# ELF-AVR-NEXT: PAddr: 0x4
721+
# ELF-AVR-NEXT: Offset: 0x78
720722
# ELF-AVR-NEXT: Sections:
721723
# ELF-AVR-NEXT: - Name: .text
722724
# ELF-AVR-NEXT: Type: SHT_PROGBITS

llvm/test/tools/obj2yaml/ELF/program-headers.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,48 +42,57 @@
4242
# YAML-NEXT: FirstSec: .hash
4343
# YAML-NEXT: LastSec: .dynstr
4444
# YAML-NEXT: Align: 0x1000
45+
# YAML-NEXT: Offset: 0x0
4546
# YAML-NEXT: - Type: PT_LOAD
4647
# YAML-NEXT: Flags: [ PF_X, PF_R ]
4748
# YAML-NEXT: FirstSec: .foo
4849
# YAML-NEXT: LastSec: .zed
4950
# YAML-NEXT: VAddr: 0x1000
5051
# YAML-NEXT: Align: 0x1000
52+
# YAML-NEXT: Offset: 0x281
5153
# YAML-NEXT: - Type: PT_LOAD
5254
# YAML-NEXT: Flags: [ PF_R ]
5355
# YAML-NEXT: FirstSec: '.foo (1)'
5456
# YAML-NEXT: LastSec: .baz
5557
# YAML-NEXT: VAddr: 0x2000
5658
# YAML-NEXT: Align: 0x1000
59+
# YAML-NEXT: Offset: 0x291
5760
# YAML-NEXT: - Type: PT_LOAD
5861
# YAML-NEXT: Flags: [ PF_W, PF_R ]
5962
# YAML-NEXT: FirstSec: .dynamic
6063
# YAML-NEXT: LastSec: .dynamic.tail
6164
# YAML-NEXT: VAddr: 0x3EF0
6265
# YAML-NEXT: Align: 0x1000
66+
# YAML-NEXT: Offset: 0x29A
6367
# YAML-NEXT: - Type: PT_DYNAMIC
6468
# YAML-NEXT: Flags: [ PF_W, PF_R ]
6569
# YAML-NEXT: FirstSec: .dynamic
6670
# YAML-NEXT: LastSec: .dynamic
6771
# YAML-NEXT: VAddr: 0x3EF0
6872
# YAML-NEXT: Align: 0x8
73+
# YAML-NEXT: Offset: 0x29A
6974
# YAML-NEXT: - Type: PT_GNU_RELRO
7075
# YAML-NEXT: Flags: [ PF_R ]
7176
# YAML-NEXT: FirstSec: .dynamic
7277
# YAML-NEXT: LastSec: .dynamic
7378
# YAML-NEXT: VAddr: 0x3EF0
79+
# YAML-NEXT: Offset: 0x29A
7480
# YAML-NEXT: - Type: PT_LOAD
7581
# YAML-NEXT: Flags: [ PF_R ]
7682
# YAML-NEXT: VAddr: 0x4000
83+
# YAML-NEXT: Offset: 0x0
7784
# YAML-NEXT: - Type: PT_LOAD
7885
# YAML-NEXT: Flags: [ PF_R ]
7986
# YAML-NEXT: FirstSec: .gnu.hash
8087
# YAML-NEXT: LastSec: .gnu.hash
8188
# YAML-NEXT: VAddr: 0x1A0
89+
# YAML-NEXT: Offset: 0x248
8290
# YAML-NEXT: - Type: PT_LOAD
8391
# YAML-NEXT: Flags: [ PF_R ]
8492
# YAML-NEXT: FirstSec: .gnu.hash
8593
# YAML-NEXT: LastSec: .gnu.hash
8694
# YAML-NEXT: VAddr: 0x1A0
95+
# YAML-NEXT: Offset: 0x248
8796
# YAML-NEXT: Sections:
8897

8998
--- !ELF
@@ -233,21 +242,25 @@ DynamicSymbols: []
233242
# EMPTY-NEXT: LastSec: .empty.tls.end
234243
# EMPTY-NEXT: VAddr: 0x1000
235244
# EMPTY-NEXT: Align: 0x1000
245+
# EMPTY-NEXT: Offset: 0x120
236246
# EMPTY-NEXT: - Type: PT_TLS
237247
# EMPTY-NEXT: Flags: [ PF_W, PF_R ]
238248
# EMPTY-NEXT: FirstSec: .empty.tls.start
239249
# EMPTY-NEXT: LastSec: .empty.tls.start
240250
# EMPTY-NEXT: VAddr: 0x1000
251+
# EMPTY-NEXT: Offset: 0x120
241252
# EMPTY-NEXT: - Type: PT_TLS
242253
# EMPTY-NEXT: Flags: [ PF_W, PF_R ]
243254
# EMPTY-NEXT: FirstSec: .empty.tls.middle
244255
# EMPTY-NEXT: LastSec: .empty.tls.middle
245256
# EMPTY-NEXT: VAddr: 0x1100
257+
# EMPTY-NEXT: Offset: 0x220
246258
# EMPTY-NEXT: - Type: PT_TLS
247259
# EMPTY-NEXT: Flags: [ PF_W, PF_R ]
248260
# EMPTY-NEXT: FirstSec: .empty.tls.end
249261
# EMPTY-NEXT: LastSec: .empty.tls.end
250262
# EMPTY-NEXT: VAddr: 0x1200
263+
# EMPTY-NEXT: Offset: 0x320
251264
# EMPTY-NEXT: Sections:
252265

253266
--- !ELF
@@ -322,6 +335,7 @@ Sections:
322335
# MISALIGNED-YAML-NEXT: LastSec: .foo
323336
# MISALIGNED-YAML-NEXT: VAddr: 0x1000
324337
# MISALIGNED-YAML-NEXT: Align: 0x1000
338+
# MISALIGNED-YAML-NEXT: Offset: 0x77
325339
# MISALIGNED-YAML-NEXT: Sections:
326340

327341
--- !ELF
@@ -354,18 +368,22 @@ Sections:
354368
# NON-ALLOC-NEXT: Flags: [ PF_R ]
355369
# NON-ALLOC-NEXT: FirstSec: .alloc.1
356370
# NON-ALLOC-NEXT: LastSec: .non-alloc.1
371+
# NON-ALLOC-NEXT: Offset: 0x120
357372
# NON-ALLOC-NEXT: - Type: PT_LOAD
358373
# NON-ALLOC-NEXT: Flags: [ PF_R ]
359374
# NON-ALLOC-NEXT: FirstSec: .alloc.1
360375
# NON-ALLOC-NEXT: LastSec: .non-alloc.1
376+
# NON-ALLOC-NEXT: Offset: 0x120
361377
# NON-ALLOC-NEXT: - Type: PT_LOAD
362378
# NON-ALLOC-NEXT: Flags: [ PF_R ]
363379
# NON-ALLOC-NEXT: FirstSec: .alloc.2
364380
# NON-ALLOC-NEXT: LastSec: .alloc.2
381+
# NON-ALLOC-NEXT: Offset: 0x230
365382
# NON-ALLOC-NEXT: - Type: PT_LOAD
366383
# NON-ALLOC-NEXT: Flags: [ PF_R ]
367384
# NON-ALLOC-NEXT: FirstSec: .alloc.1
368385
# NON-ALLOC-NEXT: LastSec: .alloc.2
386+
# NON-ALLOC-NEXT: Offset: 0x120
369387
# NON-ALLOC-NEXT: Sections:
370388

371389
--- !ELF
@@ -418,23 +436,28 @@ Sections:
418436
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
419437
# NOBITS-NEXT: FirstSec: .bss
420438
# NOBITS-NEXT: LastSec: .bss
439+
# NOBITS-NEXT: Offset: 0x159
421440
# NOBITS-NEXT: - Type: PT_LOAD
422441
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
423442
# NOBITS-NEXT: FirstSec: .data.1
424443
# NOBITS-NEXT: LastSec: .bss
444+
# NOBITS-NEXT: Offset: 0x158
425445
# NOBITS-NEXT: - Type: PT_LOAD
426446
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
427447
# NOBITS-NEXT: FirstSec: .data.1
428448
# NOBITS-NEXT: LastSec: .data.2
449+
# NOBITS-NEXT: Offset: 0x158
429450
# NOBITS-NEXT: - Type: PT_LOAD
430451
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
431452
# NOBITS-NEXT: FirstSec: .bss
432453
# NOBITS-NEXT: LastSec: .data.2
454+
# NOBITS-NEXT: Offset: 0x159
433455
# NOBITS-NEXT: - Type: PT_LOAD
434456
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
435457
# NOBITS-NEXT: FirstSec: .foo.bss
436458
# NOBITS-NEXT: LastSec: .bar.bss
437459
# NOBITS-NEXT: VAddr: 0x200000000
460+
# NOBITS-NEXT: Offset: 0x15A
438461
# NOBITS-NEXT: Sections:
439462

440463
--- !ELF
@@ -581,6 +604,7 @@ Sections:
581604
# ZERO-SIZE-NEXT: FirstSec: .empty.bar1
582605
# ZERO-SIZE-NEXT: LastSec: .empty.bar2
583606
# ZERO-SIZE-NEXT: VAddr: 0x2000
607+
# ZERO-SIZE-NEXT: Offset: 0x78
584608
# ZERO-SIZE-NEXT: Sections:
585609

586610
--- !ELF

llvm/tools/obj2yaml/elf2yaml.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ ELFDumper<ELFT>::dumpProgramHeaders(
484484
PH.Flags = Phdr.p_flags;
485485
PH.VAddr = Phdr.p_vaddr;
486486
PH.PAddr = Phdr.p_paddr;
487+
PH.Offset = Phdr.p_offset;
487488

488489
// yaml2obj sets the alignment of a segment to 1 by default.
489490
// We do not print the default alignment to reduce noise in the output.

0 commit comments

Comments
 (0)