diff --git a/test/tools/yaml2obj/elf-custom-null-section.yaml b/test/tools/yaml2obj/elf-custom-null-section.yaml index 23b877fc4be..dc74a7bfa95 100644 --- a/test/tools/yaml2obj/elf-custom-null-section.yaml +++ b/test/tools/yaml2obj/elf-custom-null-section.yaml @@ -42,10 +42,64 @@ 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 + +# 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: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Type: SHT_NULL + 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: ls -l %t3 | tr -s ' ' | cut -d ' ' -f 5 > %t.txt +# RUN: ls -l %t4 | tr -s ' ' | cut -d ' ' -f 5 >> %t.txt +# RUN: FileCheck %s --input-file=%t.txt --check-prefix=SIZE + +# SIZE: [[FILESIZE:.*]] +# SIZE: [[FILESIZE]] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Type: SHT_NULL + Name: .foo + Flags: [ SHF_ALLOC ] + AddressAlign: 0x1 + Size: 0xFFFF + EntSize: 0x3 + Link: 4 + Info: 5 + Address: 0x6 + +## 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=OTHER-SECTION # OTHER-SECTION: Section Headers: # OTHER-SECTION-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al @@ -72,46 +126,6 @@ Sections: - 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 @@ -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: @@ -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 diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index c6be508a64a..e11d8fe3ff0 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -247,7 +247,7 @@ void ELFState::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"); } @@ -327,30 +327,15 @@ bool ELFState::initSectionHeaders(ELFState &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(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; @@ -372,7 +357,17 @@ bool ELFState::initSectionHeaders(ELFState &State, SHeader.sh_link = Index; } - if (auto S = dyn_cast(Sec)) { + if (I == 0) { + if (auto RawSec = dyn_cast(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(Sec)) { if (!writeSectionContent(SHeader, *S, CBA)) return false; } else if (auto S = dyn_cast(Sec)) { @@ -966,8 +961,11 @@ bool ELFState::writeSectionContent(Elf_Shdr &SHeader, } template bool ELFState::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