1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[yaml2obj] - Add a support for defining null sections in YAMLs.

ELF spec shows (Figure 4-10: Section Header Table Entry:Index 0,
http://www.sco.com/developers/gabi/latest/ch4.sheader.html)
that section header at index 0 (null section) can have sh_size and
sh_link fields set to non-zero values.

It says (https://docs.oracle.com/cd/E19683-01/817-3677/6mj8mbtc9/index.html):

"If the number of sections is greater than or equal to SHN_LORESERVE (0xff00),
this member has the value zero and the actual number of section header table
entries is contained in the sh_size field of the section header at index 0.
Otherwise, the sh_size member of the initial entry contains 0."

and:

"If the section name string table section index is greater than or equal to SHN_LORESERVE
(0xff00), this member has the value SHN_XINDEX (0xffff) and the actual index of the section
name string table section is contained in the sh_link field of the section header at index 0.
Otherwise, the sh_link member of the initial entry contains 0."

At this moment it is not possible to create custom section headers at index 0 using yaml2obj.

This patch implements this.

Differential revision: https://reviews.llvm.org/D64913

llvm-svn: 366794
This commit is contained in:
George Rimar 2019-07-23 11:03:37 +00:00
parent e41cdbc1ed
commit f6a14760a7
2 changed files with 192 additions and 5 deletions

View File

@ -0,0 +1,169 @@
## In this test we check that can redefine the null section in the YAML.
## Test the default output first.
# RUN: yaml2obj --docnum=1 %s -o %t1
# RUN: llvm-readelf --sections %t1 | FileCheck %s --check-prefix=DEFAULT
# DEFAULT: Section Headers:
# DEFAULT-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# DEFAULT-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
# DEFAULT-NEXT: [ 1] .symtab SYMTAB 0000000000000000 000140 000018 18 2 1 8
# DEFAULT-NEXT: [ 2] .strtab STRTAB 0000000000000000 000158 000001 00 0 0 1
# DEFAULT-NEXT: [ 3] .shstrtab STRTAB 0000000000000000 000159 00001b 00 0 0 1
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
## Now define a SHT_NULL section with fields all zeroed.
## In this case it is equal to the section created by default.
# RUN: yaml2obj --docnum=2 %s -o %t2
# RUN: llvm-readelf --sections %t2 | FileCheck %s --check-prefix=DEFAULT
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
Name: ''
Flags: [ ]
AddressAlign: 0x0
Size: 0x0
EntSize: 0x0
Link: 0
Info: 0
Address: 0x0
## Check we are still able to describe other sections too.
# RUN: yaml2obj --docnum=3 %s -o %t3
# RUN: llvm-readelf --sections %t3 | FileCheck %s --check-prefix=OTHER-SECTION
# OTHER-SECTION: Section Headers:
# OTHER-SECTION-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# OTHER-SECTION-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
# OTHER-SECTION-NEXT: [ 1] foo PROGBITS 0000000000000000 000180 000000 00 0 0 0
# OTHER-SECTION-NEXT: [ 2] .symtab SYMTAB 0000000000000000 000180 000018 18 3 1 8
# OTHER-SECTION-NEXT: [ 3] .strtab STRTAB 0000000000000000 000198 000001 00 0 0 1
# OTHER-SECTION-NEXT: [ 4] .shstrtab STRTAB 0000000000000000 000199 00001f 00 0 0 1
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
Name: ''
Flags: [ ]
AddressAlign: 0x0
Size: 0x0
EntSize: 0x0
Link: 0
- Type: SHT_PROGBITS
Name: 'foo'
## Check we can redefine sh_size and sh_link fields of the SHT_NULL section.
# RUN: yaml2obj --docnum=4 %s -o %t4
# RUN: llvm-readelf --sections %t4 | FileCheck %s --check-prefix=REDEFINE
# REDEFINE: Section Headers:
# REDEFINE-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# REDEFINE-NEXT: [ 0] NULL 0000000000000000 000000 000123 00 1 0 0
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
Link: .foo
Size: 0x123
- Type: SHT_PROGBITS
Name: .foo
## The same as above, but using a number as a Link value.
# RUN: yaml2obj --docnum=5 %s -o %t5
# RUN: llvm-readelf --sections %t5 | FileCheck %s --check-prefix=REDEFINE
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
Link: 1
Size: 0x123
- Type: SHT_PROGBITS
Name: .foo
## Check we report an error if null section sh_link field refers to an unknown section.
# RUN: not yaml2obj --docnum=6 %s -o %t6 2>&1 | FileCheck %s --check-prefix=CASE4
# CASE4: error: Unknown section referenced: '.foo' at YAML section ''.
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
Link: .foo
## Check that null section fields are set to zero, if they are unspecified.
# RUN: yaml2obj --docnum=7 %s -o %t7
# RUN: llvm-readelf --sections %t7 | FileCheck %s --check-prefix=DEFAULT
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
## Check we do not crash if we have more than one SHT_NULL section.
# RUN: yaml2obj --docnum=8 %s -o %t8
# RUN: llvm-readelf --sections %t8 | FileCheck %s --check-prefix=MULTIPLE
# MULTIPLE: Section Headers:
# MULTIPLE-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# MULTIPLE-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
# MULTIPLE-NEXT: [ 1] NULL 0000000000000123 000180 000020 10 A 1 2 0
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
- Type: SHT_NULL
Flags: [ SHF_ALLOC ]
Size: 0x20
EntSize: 0x10
Link: 1
Info: 2
Address: 0x123

View File

@ -192,10 +192,11 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D) : Doc(D) {
if (!D->Name.empty())
DocSections.insert(D->Name);
// Insert SHT_NULL section implicitly.
Doc.Sections.insert(
Doc.Sections.begin(),
llvm::make_unique<ELFYAML::Section>(
// Insert SHT_NULL section implicitly when it is not defined in YAML.
if (Doc.Sections.empty() || Doc.Sections.front()->Type != ELF::SHT_NULL)
Doc.Sections.insert(
Doc.Sections.begin(),
llvm::make_unique<ELFYAML::Section>(
ELFYAML::Section::SectionKind::RawContent, /*IsImplicit=*/true));
std::vector<StringRef> ImplicitSections = {".symtab", ".strtab", ".shstrtab"};
@ -325,10 +326,27 @@ bool ELFState<ELFT>::initSectionHeaders(ELFState<ELFT> &State,
// valid SHN_UNDEF entry since SHT_NULL == 0.
SHeaders.resize(Doc.Sections.size());
for (size_t I = 1; I < Doc.Sections.size(); ++I) {
for (size_t I = 0; I < Doc.Sections.size(); ++I) {
Elf_Shdr &SHeader = SHeaders[I];
ELFYAML::Section *Sec = Doc.Sections[I].get();
if (I == 0) {
if (Sec->IsImplicit)
continue;
if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec))
if (S->Size)
SHeader.sh_size = *S->Size;
if (!Sec->Link.empty()) {
unsigned Index;
if (!convertSectionIndex(SN2I, Sec->Name, Sec->Link, Index))
return false;
SHeader.sh_link = Index;
}
continue;
}
// We have a few sections like string or symbol tables that are usually
// added implicitly to the end. However, if they are explicitly specified
// in the YAML, we need to write them here. This ensures the file offset