Skip to content

Commit

Permalink
[yaml2obj] - Allow custom fields for the SHT_UNDEF sections.
Browse files Browse the repository at this point in the history
This is a follow-up refactoring patch for recently
introduced functionality which which reduces the code duplication
and also makes possible to redefine all possible fields of
the first SHT_NULL section (previously it was only possible to set
sh_link and sh_size).

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

llvm-svn: 366894
  • Loading branch information
George Rimar committed Jul 24, 2019
1 parent bdc6b6e commit 242da4e
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 55 deletions.
106 changes: 71 additions & 35 deletions llvm/test/tools/yaml2obj/elf-custom-null-section.yaml
Expand Up @@ -42,18 +42,14 @@ Sections:
Info: 0
Address: 0x0

## Check we are still able to describe other sections too.
## Check we can redefine fields of the first SHT_NULL section.

# RUN: yaml2obj --docnum=3 %s -o %t3
# RUN: llvm-readelf --sections %t3 | FileCheck %s --check-prefix=OTHER-SECTION
# RUN: llvm-readelf --sections %t3 | FileCheck %s --check-prefix=REDEFINE

# 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
# REDEFINE: Section Headers:
# REDEFINE-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# REDEFINE-NEXT: [ 0] .foo NULL 0000000000000006 000000 000002 03 A 4 5 1

--- !ELF
FileHeader:
Expand All @@ -63,23 +59,25 @@ FileHeader:
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.
Name: .foo
Flags: [ SHF_ALLOC ]
AddressAlign: 0x1
Size: 0x2
EntSize: 0x3
Link: 4
Info: 5
Address: 0x6

## Check that file size does not change if we redefine the Size
## of the first SHT_NULL section.

# RUN: yaml2obj --docnum=4 %s -o %t4
# RUN: llvm-readelf --sections %t4 | FileCheck %s --check-prefix=REDEFINE
# RUN: stat %t3 > %t.txt
# RUN: stat %t4 >> %t.txt
# RUN: FileCheck %s --input-file=%t.txt --check-prefix=SIZE

# 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
# SIZE: Size: [[FILESIZE:.*]]
# SIZE: Size: [[FILESIZE]]

--- !ELF
FileHeader:
Expand All @@ -88,16 +86,28 @@ FileHeader:
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
Link: .foo
Size: 0x123
- Type: SHT_PROGBITS
Name: .foo
- Type: SHT_NULL
Name: .foo
Flags: [ SHF_ALLOC ]
AddressAlign: 0x1
Size: 0xFFFF
EntSize: 0x3
Link: 4
Info: 5
Address: 0x6

## The same as above, but using a number as a Link value.
## Check we are still able to describe other sections too.

# RUN: yaml2obj --docnum=5 %s -o %t5
# RUN: llvm-readelf --sections %t5 | FileCheck %s --check-prefix=REDEFINE
# RUN: llvm-readelf --sections %t5 | 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:
Expand All @@ -106,11 +116,15 @@ FileHeader:
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
Link: 1
Size: 0x123
- Type: SHT_NULL
Name: ''
Flags: [ ]
AddressAlign: 0x0
Size: 0x0
EntSize: 0x0
Link: 0
- Type: SHT_PROGBITS
Name: .foo
Name: 'foo'

## Check we report an error if null section sh_link field refers to an unknown section.

Expand Down Expand Up @@ -150,7 +164,7 @@ Sections:
# 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
# MULTIPLE-NEXT: [ 1] .foo NULL 0000000000000123 000180 000020 10 A 1 2 0

--- !ELF
FileHeader:
Expand All @@ -161,9 +175,31 @@ FileHeader:
Sections:
- Type: SHT_NULL
- Type: SHT_NULL
Name: .foo
Flags: [ SHF_ALLOC ]
Size: 0x20
EntSize: 0x10
Link: 1
Info: 2
Address: 0x123

## Check we can override the sh_offset/sh_size fields of the first SHT_NULL section if requested.

# RUN: yaml2obj --docnum=9 %s -o %t9
# RUN: llvm-readelf --sections %t9 | FileCheck %s --check-prefix=OVERRIDE

# OVERRIDE: Section Headers:
# OVERRIDE-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
# OVERRIDE-NEXT: [ 0] NULL 0000000000000000 000007 000008 00 0 0 0

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Type: SHT_NULL
Size: 0x2
ShOffset: 0x7
ShSize: 0x8
38 changes: 18 additions & 20 deletions llvm/tools/yaml2obj/yaml2elf.cpp
Expand Up @@ -247,7 +247,7 @@ void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
? (typename ELFT::uint)(*Doc.Header.SHOffset)
: sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
Header.e_shnum =
Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : SN2I.size() + 1;
Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : Doc.Sections.size();
Header.e_shstrndx = Doc.Header.SHStrNdx ? (uint16_t)*Doc.Header.SHStrNdx
: SN2I.get(".shstrtab");
}
Expand Down Expand Up @@ -327,30 +327,15 @@ bool ELFState<ELFT>::initSectionHeaders(ELFState<ELFT> &State,
SHeaders.resize(Doc.Sections.size());

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;
}
if (I == 0 && Sec->IsImplicit)
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
// remains correct.
Elf_Shdr &SHeader = SHeaders[I];
if (initImplicitHeader(State, CBA, SHeader, Sec->Name,
Sec->IsImplicit ? nullptr : Sec))
continue;
Expand All @@ -372,7 +357,17 @@ bool ELFState<ELFT>::initSectionHeaders(ELFState<ELFT> &State,
SHeader.sh_link = Index;
}

if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
if (I == 0) {
if (auto RawSec = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
// We do not write any content for special SHN_UNDEF section.
if (RawSec->Size)
SHeader.sh_size = *RawSec->Size;
if (RawSec->Info)
SHeader.sh_info = *RawSec->Info;
}
if (Sec->EntSize)
SHeader.sh_entsize = *Sec->EntSize;
} else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
if (!writeSectionContent(SHeader, *S, CBA))
return false;
} else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec)) {
Expand Down Expand Up @@ -966,8 +961,11 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
}

template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
for (unsigned I = 1, E = Doc.Sections.size(); I != E; ++I) {
for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) {
StringRef Name = Doc.Sections[I]->Name;
if (Name.empty())
continue;

DotShStrtab.add(dropUniqueSuffix(Name));
if (!SN2I.addName(Name, I)) {
WithColor::error() << "Repeated section name: '" << Name
Expand Down

0 comments on commit 242da4e

Please sign in to comment.