llvm-project/llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml
Ruoyu Qiu c1fca0fa14
[llvm][yaml2obj] Modify section header overriding timing (#130942)
yaml2obj should determine the program header offset (and other
properties) based on the intended values rather than the final
`sh_offset` of the section header.

`setProgramHeaderLayout` uses section offsets for determining
`p_offset`. Move section header overriding after
`setProgramHeaderLayout` to prevent `ShOffset` from affecting program
header `p_offset`.

This change adjusts the timing of when the section header is overridden
to ensure that the program headers are set correctly.

More details
[here](https://github.com/llvm/llvm-project/pull/126537#issuecomment-2700421989).

---------

Signed-off-by: Ruoyu Qiu <cabbaken@outlook.com>
Signed-off-by: Ruoyu Qiu <qiuruoyu@xiaomi.com>
Co-authored-by: Ruoyu Qiu <qiuruoyu@xiaomi.com>
2025-09-18 08:37:50 +01:00

209 lines
5.3 KiB
YAML

## Show that yaml2obj properly emits program headers with explicit file size,
## memory size and offset parameters.
# RUN: yaml2obj --docnum=1 %s -o %t1
# RUN: llvm-readobj %t1 --program-headers | FileCheck %s
# CHECK: ProgramHeaders [
# CHECK: Offset: 0x1234
# CHECK: FileSize: 1111
# CHECK: MemSize: 9999
# CHECK: Offset: 0x2000
# CHECK: FileSize: 6
# CHECK: MemSize: 4
# CHECK: Offset: 0x2000
# CHECK: FileSize: 4
# CHECK: MemSize: 6
# CHECK: Offset: 0x1FFF
# CHECK: FileSize: 5
# CHECK: MemSize: 5
# CHECK: Offset: 0xFFE
# CHECK: FileSize: 7
# CHECK: MemSize: 9
# CHECK: Offset: 0x3000
# CHECK: FileSize: 3
# CHECK: MemSize: 2
# CHECK: Offset: 0x2004
## Offset of .nobits2 (0x2009) - offset of .data (0x2004) == 0x5.
# CHECK: FileSize: 5
# CHECK: MemSize: 6
# CHECK: ]
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
Offset: 0x1000
AddressAlign: 0x1000
- Name: .rodata
Type: SHT_PROGBITS
Size: 4
Offset: 0x2000
AddressAlign: 0x1000
- Name: .data
Type: SHT_PROGBITS
Offset: 0x2004
Size: 4
- Name: .nobits1
Type: SHT_NOBITS
Offset: 0x2008
Size: 1
- Name: .nobits2
Type: SHT_NOBITS
# Intentionally set to 0x2009 though the previous section is SHT_NOBITS.
Offset: 0x2009
Size: 1
ProgramHeaders:
# Program header with no sections.
- Type: 0x6abcdef0 # arbitrary type
Offset: 0x1234
FileSize: 1111
MemSize: 9999
# Program header with only file size set.
- Type: 0x6abcdef0
FileSize: 6
FirstSec: .rodata
LastSec: .rodata
# Program header with only mem size set.
- Type: 0x6abcdef0
MemSize: 6
FirstSec: .rodata
LastSec: .rodata
# Program header with only offset set.
- Type: 0x6abcdef0
Offset: 0x1fff
FirstSec: .rodata
LastSec: .rodata
# Program header with sections, valid properties.
- Type: 0x6abcdef0
Offset: 0xffe
FileSize: 7
MemSize: 9
FirstSec: .text
LastSec: .text
# Program header with invalid properties.
- Type: 0x6abcdef0
Offset: 0x3000
FileSize: 3
MemSize: 2
# Program header with 2 SHT_NOBITS sections.
- Type: 0x6abcdef0
Offset: 0x2004
FirstSec: .data
LastSec: .nobits2
## Test the "Offset" property.
## Check that by default the p_offset field of a segment is set to the
## offset of the section with the minimum offset.
# RUN: yaml2obj --docnum=2 %s -o %t2
# RUN: llvm-readelf %t2 --sections --program-headers | \
# RUN: FileCheck %s --check-prefixes=DEFAULT-OFFSET
# DEFAULT-OFFSET: [Nr] Name Type Address Off
# DEFAULT-OFFSET: [ 1] .foo PROGBITS 0000000000001000 0000b0
# DEFAULT-OFFSET-NEXT: [ 2] .bar PROGBITS 0000000000001001 0000b1
# DEFAULT-OFFSET: Type Offset
# DEFAULT-OFFSET-NEXT: LOAD 0x0000b0
# DEFAULT-OFFSET-NEXT: LOAD 0x0000b1
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
Size: 0x1
Address: 0x1000
- Name: .bar
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
Size: 0x1
ProgramHeaders:
- Type: PT_LOAD
FirstSec: .foo
LastSec: .bar
- Type: PT_LOAD
FirstSec: .bar
LastSec: .bar
## Check we can set the "Offset" value explicitly to be less than or equal to
## the offset of a section in the segment.
# RUN: yaml2obj --docnum=3 -DOFFSET=0x77 %s -o %t3
# RUN: llvm-readelf %t3 --sections --program-headers | \
# RUN: FileCheck %s --check-prefixes=VALID-OFFSET,VALID-OFFSET-LESS
# RUN: yaml2obj --docnum=3 -DOFFSET=0x78 %s -o %t4
# RUN: llvm-readelf %t4 --sections --program-headers | \
# RUN: FileCheck %s --check-prefixes=VALID-OFFSET,VALID-OFFSET-EQ
# VALID-OFFSET: [Nr] Name Type Address Off
# VALID-OFFSET: [ 1] .foo PROGBITS 0000000000000000 000078
# VALID-OFFSET: Type Offset
# VALID-OFFSET-EQ: LOAD 0x000078
# VALID-OFFSET-LESS: LOAD 0x000077
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
Size: 0x1
ProgramHeaders:
- Type: PT_LOAD
Offset: [[OFFSET]]
FirstSec: .foo
LastSec: .foo
## Check we report an error when the "Offset" value is larger than the offset of a section in the segment.
# RUN: not yaml2obj --docnum=3 -DOFFSET=0x79 %s -o /dev/null 2>&1 | \
# RUN: FileCheck %s --check-prefix=INVALID-OFFSET
# INVALID-OFFSET: yaml2obj: error: 'Offset' for segment with index 1 must be less than or equal to the minimum file offset of all included sections (0x78)
## Check "Offset" is used before the section offset is overriden using "ShOffset".
# RUN: yaml2obj --docnum=4 %s -o %t5
# RUN: llvm-readelf %t5 --sections --program-headers | FileCheck %s --check-prefix=SHOFFSET
# SHOFFSET: [Nr] Name Type Address Off
# SHOFFSET: [ 1] .foo PROGBITS 0000000000000000 ffffffff
# SHOFFSET: Type Offset
# SHOFFSET-NEXT: LOAD 0x000078
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
Size: 0x1
ShOffset: 0xFFFFFFFF
ProgramHeaders:
- Type: PT_LOAD
Offset: 0x78
FirstSec: .foo
LastSec: .foo