Skip to content

Commit c1fca0f

Browse files
cabbakenRuoyu Qiu
andauthored
[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](#126537 (comment)). --------- Signed-off-by: Ruoyu Qiu <[email protected]> Signed-off-by: Ruoyu Qiu <[email protected]> Co-authored-by: Ruoyu Qiu <[email protected]>
1 parent e7db709 commit c1fca0f

File tree

4 files changed

+75
-46
lines changed

4 files changed

+75
-46
lines changed

llvm/lib/ObjectYAML/ELFEmitter.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ template <class ELFT> class ELFState {
206206
NameToIdxMap DynSymN2I;
207207
ELFYAML::Object &Doc;
208208

209+
std::vector<std::pair<Elf_Shdr *, ELFYAML::Section>>
210+
SectionHeadersOverrideHelper;
211+
209212
StringSet<> ExcludedSectionHeaders;
210213

211214
uint64_t LocationCounter = 0;
@@ -226,6 +229,7 @@ template <class ELFT> class ELFState {
226229
StringRef SecName, ELFYAML::Section *YAMLSec);
227230
void initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
228231
ContiguousBlobAccumulator &CBA);
232+
void overrideSectionHeaders(std::vector<Elf_Shdr> &SHeaders);
229233
void initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType,
230234
ContiguousBlobAccumulator &CBA,
231235
ELFYAML::Section *YAMLSec);
@@ -849,7 +853,7 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
849853
}
850854

851855
LocationCounter += SHeader.sh_size;
852-
overrideFields<ELFT>(Sec, SHeader);
856+
SectionHeadersOverrideHelper.push_back({&SHeader, *Sec});
853857
continue;
854858
}
855859

@@ -903,12 +907,17 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
903907
}
904908

905909
LocationCounter += SHeader.sh_size;
906-
907-
// Override section fields if requested.
908-
overrideFields<ELFT>(Sec, SHeader);
910+
SectionHeadersOverrideHelper.push_back({&SHeader, *Sec});
909911
}
910912
}
911913

914+
template <class ELFT>
915+
void ELFState<ELFT>::overrideSectionHeaders(std::vector<Elf_Shdr> &SHeaders) {
916+
for (std::pair<Elf_Shdr *, ELFYAML::Section> &HeaderAndSec :
917+
SectionHeadersOverrideHelper)
918+
overrideFields<ELFT>(&HeaderAndSec.second, *HeaderAndSec.first);
919+
}
920+
912921
template <class ELFT>
913922
void ELFState<ELFT>::assignSectionAddress(Elf_Shdr &SHeader,
914923
ELFYAML::Section *YAMLSec) {
@@ -2105,6 +2114,11 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
21052114
// Now we can decide segment offsets.
21062115
State.setProgramHeaderLayout(PHeaders, SHeaders);
21072116

2117+
// Override section fields, if requested. This needs to happen after program
2118+
// header layout happens, because otherwise the layout will use the new
2119+
// values.
2120+
State.overrideSectionHeaders(SHeaders);
2121+
21082122
bool ReachedLimit = CBA.getOffset() > MaxSize;
21092123
if (Error E = CBA.takeLimitError()) {
21102124
// We report a custom error message instead below.

llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191

9292
## Case D: the same as "Case C", but for a 32-bit object.
9393

94-
# RUN: yaml2obj %s -DBITS=32 -DOFFSET=0xffffffff -o %t5
94+
# RUN: yaml2obj %s -DBITS=32 -DFILESIZE=8 -DOFFSET=0xffffffff -o %t5
9595
# RUN: llvm-readobj %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s \
9696
# RUN: --check-prefix=WARN5 --implicit-check-not=warning:
9797
# RUN: llvm-readelf %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s \
@@ -101,7 +101,7 @@
101101
# WARN5: warning: '[[FILE]]': unable to read the dynamic table from SHT_DYNAMIC section with index 1: offset (0xffffffff) + size (0x8) is greater than the file size (0x10c8)
102102
# WARN5: warning: '[[FILE]]': no valid dynamic table was found
103103

104-
# RUN: yaml2obj %s -DNOHEADERS=true -DBITS=32 -DOFFSET=0xffffffff -o %t5.noheaders
104+
# RUN: yaml2obj %s -DNOHEADERS=true -DBITS=32 -DFILESIZE=8 -DOFFSET=0xffffffff -o %t5.noheaders
105105
# RUN: llvm-readobj %t5.noheaders --dynamic-table 2>&1 | \
106106
# RUN: FileCheck -DFILE=%t5.noheaders %s --check-prefix=WARN5-NOHEADERS
107107
# RUN: llvm-readelf %t5.noheaders --dynamic-table 2>&1 | \
@@ -133,14 +133,13 @@ Sections:
133133
Type: SHT_DYNAMIC
134134
Address: 0x1000
135135
Offset: 0x1000
136-
ShOffset: [[OFFSET=<none>]]
136+
ShOffset: [[OFFSET=0x1000]]
137137
Entries:
138138
- Tag: DT_NULL
139139
Value: 0
140140
- Type: SectionHeaderTable
141141
NoHeaders: [[NOHEADERS=false]]
142142
ProgramHeaders:
143143
- Type: PT_DYNAMIC
144-
FileSize: [[FILESIZE=<none>]]
145-
FirstSec: .dynamic
146-
LastSec: .dynamic
144+
FileSize: [[FILESIZE=0x10]]
145+
Offset: [[OFFSET=0x1000]]

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

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -436,28 +436,38 @@ Sections:
436436
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
437437
# NOBITS-NEXT: FirstSec: .bss
438438
# NOBITS-NEXT: LastSec: .bss
439-
# NOBITS-NEXT: Offset: 0x159
439+
# NOBITS-NEXT: VAddr: 0x1001
440+
# NOBITS-NEXT: Offset: 0x191
440441
# NOBITS-NEXT: - Type: PT_LOAD
441442
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
442443
# NOBITS-NEXT: FirstSec: .data.1
443444
# NOBITS-NEXT: LastSec: .bss
444-
# NOBITS-NEXT: Offset: 0x158
445+
# NOBITS-NEXT: VAddr: 0x1000
446+
# NOBITS-NEXT: Offset: 0x190
445447
# NOBITS-NEXT: - Type: PT_LOAD
446448
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
447449
# NOBITS-NEXT: FirstSec: .data.1
448450
# NOBITS-NEXT: LastSec: .data.2
449-
# NOBITS-NEXT: Offset: 0x158
451+
# NOBITS-NEXT: VAddr: 0x1000
452+
# NOBITS-NEXT: Offset: 0x190
450453
# NOBITS-NEXT: - Type: PT_LOAD
451454
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
452455
# NOBITS-NEXT: FirstSec: .bss
453456
# NOBITS-NEXT: LastSec: .data.2
454-
# NOBITS-NEXT: Offset: 0x159
457+
# NOBITS-NEXT: VAddr: 0x1001
458+
# NOBITS-NEXT: Offset: 0x191
455459
# NOBITS-NEXT: - Type: PT_LOAD
456460
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
457461
# NOBITS-NEXT: FirstSec: .foo.bss
458462
# NOBITS-NEXT: LastSec: .bar.bss
459463
# NOBITS-NEXT: VAddr: 0x200000000
460-
# NOBITS-NEXT: Offset: 0x15A
464+
# NOBITS-NEXT: Offset: 0x193
465+
# NOBITS-NEXT: - Type: PT_LOAD
466+
# NOBITS-NEXT: Flags: [ PF_W, PF_R ]
467+
# NOBITS-NEXT: FirstSec: .data.3
468+
# NOBITS-NEXT: LastSec: .bss.large
469+
# NOBITS-NEXT: VAddr: 0x200000030
470+
# NOBITS-NEXT: Offset: 0x193
461471
# NOBITS-NEXT: Sections:
462472

463473
--- !ELF
@@ -471,27 +481,37 @@ ProgramHeaders:
471481
Flags: [ PF_W, PF_R ]
472482
FirstSec: .bss
473483
LastSec: .bss
484+
VAddr: 0x1001
474485
## Case 2: the SHT_NOBITS section is the last section in the segment.
475486
- Type: PT_LOAD
476487
Flags: [ PF_W, PF_R ]
477488
FirstSec: .data.1
478489
LastSec: .bss
490+
VAddr: 0x1000
479491
## Case 3: the SHT_NOBITS section is in the middle of the segment.
480492
- Type: PT_LOAD
481493
Flags: [ PF_W, PF_R ]
482494
FirstSec: .data.1
483495
LastSec: .data.2
496+
VAddr: 0x1000
484497
## Case 4: the SHT_NOBITS section is the first section in the segment.
485498
- Type: PT_LOAD
486499
Flags: [ PF_W, PF_R ]
487500
FirstSec: .bss
488501
LastSec: .data.2
502+
VAddr: 0x1001
489503
## Case 5: another two SHT_NOBITS sections in a different segment.
490504
- Type: PT_LOAD
491505
Flags: [ PF_W, PF_R ]
492506
FirstSec: .foo.bss
493507
LastSec: .bar.bss
494508
VAddr: 0x200000000
509+
## Case 6: a SHT_NOBITS section following a normal section, where the SHT_NOBITS size points past the end of the program header.
510+
- Type: PT_LOAD
511+
Flags: [ PF_W, PF_R ]
512+
FirstSec: .data.3
513+
LastSec: .bss.large
514+
VAddr: 0x200000030
495515
Sections:
496516
- Name: .data.1
497517
Type: SHT_PROGBITS
@@ -502,13 +522,13 @@ Sections:
502522
- Name: .bss
503523
Type: SHT_NOBITS
504524
Flags: [ SHF_WRITE, SHF_ALLOC ]
505-
## Use a size that is larger than the file size.
506-
ShSize: 0x00000000FFFFFFFF
507-
- Name: .data.2
508-
Type: SHT_PROGBITS
509-
Flags: [ SHF_WRITE, SHF_ALLOC ]
525+
## Use an arbitrary non-zero size.
526+
Size: 0x1
527+
- Name: .data.2
528+
Type: SHT_PROGBITS
529+
Flags: [ SHF_WRITE, SHF_ALLOC ]
510530
## Use an arbitrary size.
511-
Size: 0x1
531+
Size: 0x1
512532
- Name: .foo.bss
513533
Type: SHT_NOBITS
514534
Flags: [ SHF_WRITE, SHF_ALLOC ]
@@ -523,14 +543,26 @@ Sections:
523543
## Use an arbitrary size that is different to the size of
524544
## the previous section.
525545
Size: 0x20
546+
- Name: .data.3
547+
Type: SHT_PROGBITS
548+
Flags: [ SHF_WRITE, SHF_ALLOC ]
549+
## Use an abitrary size. Also use an address that is larger than the previous
550+
## section, because the tools expect segment addresses to be in order.
551+
Size: 0x1
552+
Address: 0x200000030
553+
- Name: .bss.large
554+
Type: SHT_NOBITS
555+
Flags: [ SHF_WRITE, SHF_ALLOC ]
556+
## Use a size that is larger than the file size.
557+
Size: 0x00000000FFFFFFFF
558+
Address: 0x200000031
526559

527560
## Check that we require sections in a program header
528561
## declaration to be sorted by their offsets.
529562
# RUN: not yaml2obj --docnum=6 %s -o %t6 2>&1 | \
530563
# RUN: FileCheck %s --check-prefix=UNSORTED --implicit-check-not="error:"
531564

532565
# UNSORTED: error: program header with index 0: the section index of .bar is greater than the index of .foo
533-
# UNSORTED-NEXT: error: sections in the program header with index 3 are not sorted by their file offset
534566

535567
--- !ELF
536568
FileHeader:
@@ -552,15 +584,6 @@ ProgramHeaders:
552584
FirstSec: .foo
553585
LastSec: .bar
554586
VAddr: 0x1000
555-
## Case 2: the .bar section is placed before the .zed section in the file,
556-
## but the sh_offset of .zed is less than the sh_offset of
557-
## the .bar section because of the "ShOffset" property.
558-
## Document we report an error for such a case.
559-
- Type: PT_LOAD
560-
Flags: [ PF_R ]
561-
FirstSec: .bar
562-
LastSec: .zed
563-
VAddr: 0x1001
564587
Sections:
565588
- Name: .foo
566589
Type: SHT_PROGBITS
@@ -571,11 +594,6 @@ Sections:
571594
Type: SHT_PROGBITS
572595
Flags: [ SHF_ALLOC ]
573596
Size: 0x1
574-
- Name: .zed
575-
Type: SHT_PROGBITS
576-
Flags: [ SHF_ALLOC ]
577-
Size: 0x1
578-
ShOffset: 0x0
579597

580598
## Check how we dump segments which contain empty sections.
581599
# RUN: yaml2obj --docnum=7 %s -o %t7

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,25 @@ Sections:
4444
- Name: .text
4545
Type: SHT_PROGBITS
4646
Size: 4
47-
ShOffset: 0x1000
47+
Offset: 0x1000
4848
AddressAlign: 0x1000
4949
- Name: .rodata
5050
Type: SHT_PROGBITS
5151
Size: 4
52-
ShOffset: 0x2000
52+
Offset: 0x2000
5353
AddressAlign: 0x1000
5454
- Name: .data
5555
Type: SHT_PROGBITS
56-
ShOffset: 0x2004
56+
Offset: 0x2004
5757
Size: 4
5858
- Name: .nobits1
5959
Type: SHT_NOBITS
60-
ShOffset: 0x2008
60+
Offset: 0x2008
6161
Size: 1
6262
- Name: .nobits2
6363
Type: SHT_NOBITS
6464
# Intentionally set to 0x2009 though the previous section is SHT_NOBITS.
65-
ShOffset: 0x2009
65+
Offset: 0x2009
6666
Size: 1
6767
ProgramHeaders:
6868
# Program header with no sections.
@@ -180,15 +180,15 @@ ProgramHeaders:
180180

181181
# 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)
182182

183-
## Document that the "Offset" value is checked after the section offset is overriden using "ShOffset".
183+
## Check "Offset" is used before the section offset is overriden using "ShOffset".
184184
# RUN: yaml2obj --docnum=4 %s -o %t5
185185
# RUN: llvm-readelf %t5 --sections --program-headers | FileCheck %s --check-prefix=SHOFFSET
186186

187187
# SHOFFSET: [Nr] Name Type Address Off
188188
# SHOFFSET: [ 1] .foo PROGBITS 0000000000000000 ffffffff
189189

190190
# SHOFFSET: Type Offset
191-
# SHOFFSET-NEXT: LOAD 0xffffff00
191+
# SHOFFSET-NEXT: LOAD 0x000078
192192

193193
--- !ELF
194194
FileHeader:
@@ -200,11 +200,9 @@ Sections:
200200
Type: SHT_PROGBITS
201201
Flags: [ SHF_ALLOC ]
202202
Size: 0x1
203-
## Note: the real .foo offset is much less than 0xFFFFFFFF or
204-
## 0xFFFFFF00, but no error is reported.
205203
ShOffset: 0xFFFFFFFF
206204
ProgramHeaders:
207205
- Type: PT_LOAD
208-
Offset: 0xFFFFFF00
206+
Offset: 0x78
209207
FirstSec: .foo
210208
LastSec: .foo

0 commit comments

Comments
 (0)