Skip to content

Commit 2bf5674

Browse files
author
Georgii Rymar
committed
[yaml2obj] - Program headers: add an additional check for Offset
The `Offset` field is used to set the file offset of a program header. In a normal object it should not be greater than the minimal offset of sections included into segment. This patch adds a check for that and adds tests. Differential revision: https://reviews.llvm.org/D78304
1 parent 87d33d9 commit 2bf5674

File tree

5 files changed

+128
-36
lines changed

5 files changed

+128
-36
lines changed

llvm/lib/ObjectYAML/ELFEmitter.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -759,12 +759,16 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
759759
reportError("sections in the program header with index " +
760760
Twine(PhdrIdx) + " are not sorted by their file offset");
761761

762-
if (YamlPhdr.Offset)
763-
PHeader.p_offset = *YamlPhdr.Offset;
764-
else if (!Fragments.empty())
765-
PHeader.p_offset = Fragments.front().Offset;
766-
else
767-
PHeader.p_offset = 0;
762+
uint64_t PhdrFileOffset = Fragments.empty() ? 0 : Fragments.front().Offset;
763+
if (YamlPhdr.Offset) {
764+
if (!Fragments.empty() && *YamlPhdr.Offset > PhdrFileOffset)
765+
reportError("'Offset' for segment with index " + Twine(PhdrIdx) +
766+
" must be less than or equal to the minimum file offset of "
767+
"all included sections (0x" +
768+
Twine::utohexstr(PhdrFileOffset) + ")");
769+
PhdrFileOffset = *YamlPhdr.Offset;
770+
}
771+
PHeader.p_offset = PhdrFileOffset;
768772

769773
// Find the maximum offset of the end of a section in order to set p_filesz
770774
// and p_memsz. When setting p_filesz, trailing SHT_NOBITS sections are not

llvm/test/Object/invalid.test

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -485,17 +485,9 @@ FileHeader:
485485
Data: ELFDATA2LSB
486486
Type: ET_EXEC
487487
Machine: EM_X86_64
488-
Sections:
489-
- Name: .dynamic
490-
Type: SHT_DYNAMIC
491-
Entries:
492-
- Tag: DT_NULL
493-
Value: 0
494488
ProgramHeaders:
495489
- Type: PT_DYNAMIC
496490
Offset: 0xffff0000
497-
Sections:
498-
- Section: .dynamic
499491

500492
## PT_DYNAMIC's p_filesz field is so large that p_offset + p_filesz is larger
501493
## than the object size. Check llvm-readobj reports it.

llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,7 @@ FileHeader:
3333
Data: ELFDATA2LSB
3434
Type: ET_EXEC
3535
Machine: EM_X86_64
36-
Sections:
37-
- Name: .foo
38-
Type: SHT_PROGBITS
39-
Size: 1
4036
ProgramHeaders:
41-
- Type: PT_LOAD
42-
Offset: 0x100000
43-
FileSize: 1
44-
Sections:
45-
- Section: .foo
37+
- Type: PT_LOAD
38+
Offset: 0x100000
39+
FileSize: 1

llvm/test/tools/llvm-readobj/ELF/gnu-notes.test

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,9 @@ FileHeader:
165165
Data: ELFDATA2LSB
166166
Type: ET_CORE
167167
Machine: EM_X86_64
168-
Sections:
169-
- Name: .note
170-
Type: SHT_NOTE
171-
Notes: []
172168
ProgramHeaders:
173-
- Type: PT_NOTE
169+
- Type: PT_NOTE
174170
Offset: 0xffff0000
175-
Sections:
176-
- Section: .note
177171

178172
## Test tools report an error if a note program header has an invalid size that
179173
## goes past the end of file.

llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml

Lines changed: 114 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
## Show that yaml2obj properly emits program headers with explicit file size,
22
## memory size and offset parameters.
33

4-
# RUN: yaml2obj %s -o %t
5-
# RUN: llvm-readobj %t --program-headers | FileCheck %s
4+
# RUN: yaml2obj --docnum=1 %s -o %t1
5+
# RUN: llvm-readobj %t1 --program-headers | FileCheck %s
66

77
# CHECK: ProgramHeaders [
88
# CHECK: Offset: 0x1234
@@ -34,7 +34,7 @@
3434
# CHECK: MemSize: 6
3535
# CHECK: ]
3636

37-
!ELF
37+
--- !ELF
3838
FileHeader:
3939
Class: ELFCLASS64
4040
Data: ELFDATA2LSB
@@ -92,17 +92,125 @@ ProgramHeaders:
9292
MemSize: 9
9393
Sections:
9494
- Section: .text
95-
# Program header with sections, invalid properties.
95+
# Program header with invalid properties.
9696
- Type: 0x6abcdef0
9797
Offset: 0x3000
9898
FileSize: 3
9999
MemSize: 2
100-
Sections:
101-
- Section: .data
102100
# Program header with 2 SHT_NOBITS sections.
103101
- Type: 0x6abcdef0
104102
Offset: 0x2004
105103
Sections:
106104
- Section: .data
107105
- Section: .nobits1
108106
- Section: .nobits2
107+
108+
## Test the "Offset" property.
109+
110+
## Check that by default the p_offset field of a segment is set to the
111+
## offset of the section with the minimum offset.
112+
# RUN: yaml2obj --docnum=2 %s -o %t2
113+
# RUN: llvm-readelf %t2 --sections --program-headers | \
114+
# RUN: FileCheck %s --check-prefixes=DEFAULT-OFFSET
115+
116+
# DEFAULT-OFFSET: [Nr] Name Type Address Off
117+
# DEFAULT-OFFSET: [ 1] .foo PROGBITS 0000000000001000 0000b0
118+
# DEFAULT-OFFSET-NEXT: [ 2] .bar PROGBITS 0000000000001001 0000b1
119+
120+
# DEFAULT-OFFSET: Type Offset
121+
# DEFAULT-OFFSET-NEXT: LOAD 0x0000b0
122+
# DEFAULT-OFFSET-NEXT: LOAD 0x0000b1
123+
124+
--- !ELF
125+
FileHeader:
126+
Class: ELFCLASS64
127+
Data: ELFDATA2LSB
128+
Type: ET_EXEC
129+
Machine: EM_X86_64
130+
Sections:
131+
- Name: .foo
132+
Type: SHT_PROGBITS
133+
Flags: [ SHF_ALLOC ]
134+
Size: 0x1
135+
Address: 0x1000
136+
- Name: .bar
137+
Type: SHT_PROGBITS
138+
Flags: [ SHF_ALLOC ]
139+
Size: 0x1
140+
ProgramHeaders:
141+
- Type: PT_LOAD
142+
Sections:
143+
- Section: .foo
144+
- Section: .bar
145+
- Type: PT_LOAD
146+
Sections:
147+
- Section: .bar
148+
149+
## Check we can set the "Offset" value explicitly to be less than or equal to
150+
## the offset of a section in the segment.
151+
# RUN: yaml2obj --docnum=3 -DOFFSET=0x77 %s -o %t3
152+
# RUN: llvm-readelf %t3 --sections --program-headers | \
153+
# RUN: FileCheck %s --check-prefixes=VALID-OFFSET,VALID-OFFSET-LESS
154+
# RUN: yaml2obj --docnum=3 -DOFFSET=0x78 %s -o %t4
155+
# RUN: llvm-readelf %t4 --sections --program-headers | \
156+
# RUN: FileCheck %s --check-prefixes=VALID-OFFSET,VALID-OFFSET-EQ
157+
158+
# VALID-OFFSET: [Nr] Name Type Address Off
159+
# VALID-OFFSET: [ 1] .foo PROGBITS 0000000000000000 000078
160+
161+
# VALID-OFFSET: Type Offset
162+
# VALID-OFFSET-EQ: LOAD 0x000078
163+
# VALID-OFFSET-LESS: LOAD 0x000077
164+
165+
--- !ELF
166+
FileHeader:
167+
Class: ELFCLASS64
168+
Data: ELFDATA2LSB
169+
Type: ET_EXEC
170+
Machine: EM_X86_64
171+
Sections:
172+
- Name: .foo
173+
Type: SHT_PROGBITS
174+
Flags: [ SHF_ALLOC ]
175+
Size: 0x1
176+
ProgramHeaders:
177+
- Type: PT_LOAD
178+
Offset: [[OFFSET]]
179+
Sections:
180+
- Section: .foo
181+
182+
## Check we report an error when the "Offset" value is larger than the offset of a section in the segment.
183+
# RUN: not yaml2obj --docnum=3 -DOFFSET=0x79 %s -o /dev/null 2>&1 | \
184+
# RUN: FileCheck %s --check-prefix=INVALID-OFFSET
185+
186+
# 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)
187+
188+
## Document that the "Offset" value is checked after the section offset is overriden using "ShOffset".
189+
# RUN: yaml2obj --docnum=4 %s -o %t5
190+
# RUN: llvm-readelf %t5 --sections --program-headers | FileCheck %s --check-prefix=SHOFFSET
191+
192+
# SHOFFSET: [Nr] Name Type Address Off
193+
# SHOFFSET: [ 1] .foo PROGBITS 0000000000000000 ffffffff
194+
195+
# SHOFFSET: Type Offset
196+
# SHOFFSET-NEXT: LOAD 0xffffff00
197+
198+
--- !ELF
199+
FileHeader:
200+
Class: ELFCLASS64
201+
Data: ELFDATA2LSB
202+
Type: ET_EXEC
203+
Machine: EM_X86_64
204+
Sections:
205+
- Name: .foo
206+
Type: SHT_PROGBITS
207+
Flags: [ SHF_ALLOC ]
208+
Size: 0x1
209+
## Note: the real .foo offset is much less than 0xFFFFFFFF or
210+
## 0xFFFFFF00, but no error is reported.
211+
ShOffset: 0xFFFFFFFF
212+
ProgramHeaders:
213+
- Type: PT_LOAD
214+
Offset: 0xFFFFFF00
215+
Sections:
216+
- Section: .foo

0 commit comments

Comments
 (0)