--- /dev/null
+## 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
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"};
// 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