Skip to content

Commit 68195b1

Browse files
author
Georgii Rymar
committed
[yaml2obj] - Allow empty SectionHeaderTable definitions.
Currently we don't allow the following definition: ``` Sections: - Type: SectionHeaderTable - Name: .foo Type: SHT_PROGBITS ``` We report an error: "SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop the section header table". It was implemented in this way earlier, when `SectionHeaderTable` was a dedicated key outside of the `Sections` list. And we did not allow to select where the table is written. Currently it makes sense to allow it, because a user might want to place the default section header table at an arbitrary position, e.g. before other sections. In this case it is not convenient and error prone to require specifying all sections: ``` Sections: - Type: SectionHeaderTable Sections: - Name: .foo - Name: .strtab - Name: .shstrtab - Name: .foo Type: SHT_PROGBITS ``` This patch allows empty SectionHeaderTable definitions. Differential revision: https://reviews.llvm.org/D95341
1 parent fc8e741 commit 68195b1

File tree

4 files changed

+19
-10
lines changed

4 files changed

+19
-10
lines changed

llvm/include/llvm/ObjectYAML/ELFYAML.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,13 +296,15 @@ struct SectionHeaderTable : Chunk {
296296
Optional<bool> NoHeaders;
297297

298298
size_t getNumHeaders(size_t SectionsNum) const {
299-
if (IsImplicit)
299+
if (IsImplicit || isDefault())
300300
return SectionsNum;
301301
if (NoHeaders)
302302
return (*NoHeaders) ? 0 : SectionsNum;
303303
return (Sections ? Sections->size() : 0) + /*Null section*/ 1;
304304
}
305305

306+
bool isDefault() const { return !Sections && !Excluded && !NoHeaders; }
307+
306308
static constexpr StringRef TypeStr = "SectionHeaderTable";
307309
};
308310

llvm/lib/ObjectYAML/ELFEmitter.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,8 @@ unsigned ELFState<ELFT>::toSectionIndex(StringRef S, StringRef LocSec,
555555
const ELFYAML::SectionHeaderTable &SectionHeaders =
556556
Doc.getSectionHeaderTable();
557557
if (SectionHeaders.IsImplicit ||
558-
(SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue()))
558+
(SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue()) ||
559+
SectionHeaders.isDefault())
559560
return Index;
560561

561562
assert(!SectionHeaders.NoHeaders.getValueOr(false) ||
@@ -1744,7 +1745,8 @@ template <class ELFT>
17441745
DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {
17451746
const ELFYAML::SectionHeaderTable &SectionHeaders =
17461747
Doc.getSectionHeaderTable();
1747-
if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders)
1748+
if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders ||
1749+
SectionHeaders.isDefault())
17481750
return DenseMap<StringRef, size_t>();
17491751

17501752
DenseMap<StringRef, size_t> Ret;

llvm/lib/ObjectYAML/ELFYAML.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,9 +1474,6 @@ std::string MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate(
14741474
if (const auto *SHT = dyn_cast<ELFYAML::SectionHeaderTable>(C.get())) {
14751475
if (SHT->NoHeaders && (SHT->Sections || SHT->Excluded || SHT->Offset))
14761476
return "NoHeaders can't be used together with Offset/Sections/Excluded";
1477-
if (!SHT->NoHeaders && !SHT->Sections && !SHT->Excluded)
1478-
return "SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop "
1479-
"the section header table";
14801477
return "";
14811478
}
14821479

llvm/test/tools/yaml2obj/ELF/section-headers.yaml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,28 @@ Sections:
151151
Sections: []
152152
NoHeaders: [[NOHEADERS]]
153153

154-
## Check that we do not allow an empty SectionHeaderTable tag and suggest to use an explicit syntax instead.
155-
# RUN: not yaml2obj %s --docnum=5 -o /dev/null 2>&1 | FileCheck %s --check-prefix=NO-VALUE
154+
## Check that we allow using an empty SectionHeaderTable definition.
155+
## It can be used to emit the default section header table at an arbitrary position.
156156

157-
# NO-VALUE: SectionHeaderTable can't be empty. Use 'NoHeaders' key to drop the section header table
157+
# RUN: yaml2obj %s --docnum=5 -o %t5.novalues
158+
# RUN: llvm-readelf --sections %t5.novalues | \
159+
# RUN: FileCheck %s --check-prefix=NO-VALUES
160+
161+
## Check we placed the section header table before the .foo section.
162+
163+
# NO-VALUES: There are 4 section headers, starting at offset 0x40:
164+
# NO-VALUES: [Nr] Name Type Address Off Size
165+
# NO-VALUES: [ 1] .foo PROGBITS 0000000000000000 000140 000000
158166

159167
--- !ELF
160168
FileHeader:
161169
Class: ELFCLASS64
162170
Data: ELFDATA2LSB
163171
Type: ET_REL
164172
Sections:
173+
- Type: SectionHeaderTable
165174
- Name: .foo
166175
Type: SHT_PROGBITS
167-
- Type: SectionHeaderTable
168176

169177
## Test that we are still able to override e_shoff, e_shnum and e_shstrndx
170178
## fields even when we do not produce section headers.

0 commit comments

Comments
 (0)