[llvm] 8545093 - [obj2yaml] Emit ProgramHeader.Offset

Job Noorman via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 25 01:22:03 PDT 2023


Author: Job Noorman
Date: 2023-09-25T10:21:53+02:00
New Revision: 8545093715c4efcfe7069aa29e9372d32f9c7b36

URL: https://github.com/llvm/llvm-project/commit/8545093715c4efcfe7069aa29e9372d32f9c7b36
DIFF: https://github.com/llvm/llvm-project/commit/8545093715c4efcfe7069aa29e9372d32f9c7b36.diff

LOG: [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

Added: 
    

Modified: 
    llvm/test/Object/obj2yaml.test
    llvm/test/tools/obj2yaml/ELF/program-headers.yaml
    llvm/tools/obj2yaml/elf2yaml.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/Object/obj2yaml.test b/llvm/test/Object/obj2yaml.test
index f07172595173fb8..dea9cf41eab5496 100644
--- a/llvm/test/Object/obj2yaml.test
+++ b/llvm/test/Object/obj2yaml.test
@@ -711,12 +711,14 @@ FileHeader:
 # ELF-AVR-NEXT:    FirstSec: .text
 # ELF-AVR-NEXT:    LastSec:  .text
 # ELF-AVR-NEXT:    Align:    0x2
+# ELF-AVR-NEXT:    Offset:   0x74
 # ELF-AVR-NEXT:  - Type:     PT_LOAD
 # ELF-AVR-NEXT:    Flags:    [ PF_W, PF_R ]
 # ELF-AVR-NEXT:    FirstSec: .data
 # ELF-AVR-NEXT:    LastSec:  .data
 # ELF-AVR-NEXT:    VAddr:    0x800060
 # ELF-AVR-NEXT:    PAddr:    0x4
+# ELF-AVR-NEXT:    Offset:   0x78
 # ELF-AVR-NEXT: Sections:
 # ELF-AVR-NEXT:   - Name:            .text
 # ELF-AVR-NEXT:     Type:            SHT_PROGBITS

diff  --git a/llvm/test/tools/obj2yaml/ELF/program-headers.yaml b/llvm/test/tools/obj2yaml/ELF/program-headers.yaml
index e9c12a21a0bc6f8..1d620d54019ba5d 100644
--- a/llvm/test/tools/obj2yaml/ELF/program-headers.yaml
+++ b/llvm/test/tools/obj2yaml/ELF/program-headers.yaml
@@ -42,48 +42,57 @@
 # YAML-NEXT:    FirstSec: .hash
 # YAML-NEXT:    LastSec:  .dynstr
 # YAML-NEXT:    Align:    0x1000
+# YAML-NEXT:    Offset:   0x0
 # YAML-NEXT:  - Type:     PT_LOAD
 # YAML-NEXT:    Flags:    [ PF_X, PF_R ]
 # YAML-NEXT:    FirstSec: .foo
 # YAML-NEXT:    LastSec:  .zed
 # YAML-NEXT:    VAddr:    0x1000
 # YAML-NEXT:    Align:    0x1000
+# YAML-NEXT:    Offset:   0x281
 # YAML-NEXT:  - Type:     PT_LOAD
 # YAML-NEXT:    Flags:    [ PF_R ]
 # YAML-NEXT:    FirstSec: '.foo (1)'
 # YAML-NEXT:    LastSec:  .baz
 # YAML-NEXT:    VAddr:    0x2000
 # YAML-NEXT:    Align:    0x1000
+# YAML-NEXT:    Offset:   0x291
 # YAML-NEXT:  - Type:     PT_LOAD
 # YAML-NEXT:    Flags:    [ PF_W, PF_R ]
 # YAML-NEXT:    FirstSec: .dynamic
 # YAML-NEXT:    LastSec:  .dynamic.tail
 # YAML-NEXT:    VAddr:    0x3EF0
 # YAML-NEXT:    Align:    0x1000
+# YAML-NEXT:    Offset:   0x29A
 # YAML-NEXT:  - Type:     PT_DYNAMIC
 # YAML-NEXT:    Flags:    [ PF_W, PF_R ]
 # YAML-NEXT:    FirstSec: .dynamic
 # YAML-NEXT:    LastSec:  .dynamic
 # YAML-NEXT:    VAddr:    0x3EF0
 # YAML-NEXT:    Align:    0x8
+# YAML-NEXT:    Offset:   0x29A
 # YAML-NEXT:  - Type:     PT_GNU_RELRO
 # YAML-NEXT:    Flags:    [ PF_R ]
 # YAML-NEXT:    FirstSec: .dynamic
 # YAML-NEXT:    LastSec:  .dynamic
 # YAML-NEXT:    VAddr:    0x3EF0
+# YAML-NEXT:    Offset:   0x29A
 # YAML-NEXT:  - Type:  PT_LOAD
 # YAML-NEXT:    Flags: [ PF_R ]
 # YAML-NEXT:    VAddr: 0x4000
+# YAML-NEXT:    Offset:   0x0
 # YAML-NEXT:  - Type:     PT_LOAD
 # YAML-NEXT:    Flags:    [ PF_R ]
 # YAML-NEXT:    FirstSec: .gnu.hash
 # YAML-NEXT:    LastSec:  .gnu.hash
 # YAML-NEXT:    VAddr:    0x1A0
+# YAML-NEXT:    Offset:   0x248
 # YAML-NEXT:  - Type:     PT_LOAD
 # YAML-NEXT:    Flags:    [ PF_R ]
 # YAML-NEXT:    FirstSec: .gnu.hash
 # YAML-NEXT:    LastSec:  .gnu.hash
 # YAML-NEXT:    VAddr:    0x1A0
+# YAML-NEXT:    Offset:   0x248
 # YAML-NEXT: Sections:
 
 --- !ELF
@@ -233,21 +242,25 @@ DynamicSymbols: []
 # EMPTY-NEXT:   LastSec:  .empty.tls.end
 # EMPTY-NEXT:   VAddr:    0x1000
 # EMPTY-NEXT:   Align:    0x1000
+# EMPTY-NEXT:   Offset:   0x120
 # EMPTY-NEXT: - Type:     PT_TLS
 # EMPTY-NEXT:   Flags:    [ PF_W, PF_R ]
 # EMPTY-NEXT:   FirstSec: .empty.tls.start
 # EMPTY-NEXT:   LastSec:  .empty.tls.start
 # EMPTY-NEXT:   VAddr:    0x1000
+# EMPTY-NEXT:   Offset:   0x120
 # EMPTY-NEXT: - Type:     PT_TLS
 # EMPTY-NEXT:   Flags:    [ PF_W, PF_R ]
 # EMPTY-NEXT:   FirstSec: .empty.tls.middle
 # EMPTY-NEXT:   LastSec:  .empty.tls.middle
 # EMPTY-NEXT:   VAddr:    0x1100
+# EMPTY-NEXT:   Offset:   0x220
 # EMPTY-NEXT: - Type:     PT_TLS
 # EMPTY-NEXT:   Flags:    [ PF_W, PF_R ]
 # EMPTY-NEXT:   FirstSec: .empty.tls.end
 # EMPTY-NEXT:   LastSec:  .empty.tls.end
 # EMPTY-NEXT:   VAddr:    0x1200
+# EMPTY-NEXT:   Offset:   0x320
 # EMPTY-NEXT: Sections:
 
 --- !ELF
@@ -322,6 +335,7 @@ Sections:
 # MISALIGNED-YAML-NEXT:    LastSec:  .foo
 # MISALIGNED-YAML-NEXT:    VAddr:    0x1000
 # MISALIGNED-YAML-NEXT:    Align:    0x1000
+# MISALIGNED-YAML-NEXT:    Offset:   0x77
 # MISALIGNED-YAML-NEXT: Sections:
 
 --- !ELF
@@ -354,18 +368,22 @@ Sections:
 # NON-ALLOC-NEXT:   Flags:    [ PF_R ]
 # NON-ALLOC-NEXT:   FirstSec: .alloc.1
 # NON-ALLOC-NEXT:   LastSec:  .non-alloc.1
+# NON-ALLOC-NEXT:   Offset:   0x120
 # NON-ALLOC-NEXT: - Type:     PT_LOAD
 # NON-ALLOC-NEXT:   Flags:    [ PF_R ]
 # NON-ALLOC-NEXT:   FirstSec: .alloc.1
 # NON-ALLOC-NEXT:   LastSec:  .non-alloc.1
+# NON-ALLOC-NEXT:   Offset:   0x120
 # NON-ALLOC-NEXT: - Type:     PT_LOAD
 # NON-ALLOC-NEXT:   Flags:    [ PF_R ]
 # NON-ALLOC-NEXT:   FirstSec: .alloc.2
 # NON-ALLOC-NEXT:   LastSec:  .alloc.2
+# NON-ALLOC-NEXT:   Offset:   0x230
 # NON-ALLOC-NEXT: - Type:     PT_LOAD
 # NON-ALLOC-NEXT:   Flags:    [ PF_R ]
 # NON-ALLOC-NEXT:   FirstSec: .alloc.1
 # NON-ALLOC-NEXT:   LastSec:  .alloc.2
+# NON-ALLOC-NEXT:   Offset:   0x120
 # NON-ALLOC-NEXT: Sections:
 
 --- !ELF
@@ -418,23 +436,28 @@ Sections:
 # NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
 # NOBITS-NEXT:     FirstSec: .bss
 # NOBITS-NEXT:     LastSec:  .bss
+# NOBITS-NEXT:     Offset:   0x159
 # NOBITS-NEXT:   - Type:     PT_LOAD
 # NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
 # NOBITS-NEXT:     FirstSec: .data.1
 # NOBITS-NEXT:     LastSec:  .bss
+# NOBITS-NEXT:     Offset:   0x158
 # NOBITS-NEXT:   - Type:     PT_LOAD
 # NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
 # NOBITS-NEXT:     FirstSec: .data.1
 # NOBITS-NEXT:     LastSec:  .data.2
+# NOBITS-NEXT:     Offset:   0x158
 # NOBITS-NEXT:   - Type:     PT_LOAD
 # NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
 # NOBITS-NEXT:     FirstSec: .bss
 # NOBITS-NEXT:     LastSec:  .data.2
+# NOBITS-NEXT:     Offset:   0x159
 # NOBITS-NEXT:   - Type:     PT_LOAD
 # NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
 # NOBITS-NEXT:     FirstSec: .foo.bss
 # NOBITS-NEXT:     LastSec:  .bar.bss
 # NOBITS-NEXT:     VAddr:    0x200000000
+# NOBITS-NEXT:     Offset:   0x15A
 # NOBITS-NEXT: Sections:
 
 --- !ELF
@@ -581,6 +604,7 @@ Sections:
 # ZERO-SIZE-NEXT:     FirstSec: .empty.bar1
 # ZERO-SIZE-NEXT:     LastSec:  .empty.bar2
 # ZERO-SIZE-NEXT:     VAddr:    0x2000
+# ZERO-SIZE-NEXT:     Offset:   0x78
 # ZERO-SIZE-NEXT: Sections:
 
 --- !ELF

diff  --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 40f6d5217949bcf..7c4a8853ee2d301 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -484,6 +484,7 @@ ELFDumper<ELFT>::dumpProgramHeaders(
     PH.Flags = Phdr.p_flags;
     PH.VAddr = Phdr.p_vaddr;
     PH.PAddr = Phdr.p_paddr;
+    PH.Offset = Phdr.p_offset;
 
     // yaml2obj sets the alignment of a segment to 1 by default.
     // We do not print the default alignment to reduce noise in the output.


        


More information about the llvm-commits mailing list