Index: test/tools/obj2yaml/elf-custom-null-section.yaml =================================================================== --- /dev/null +++ test/tools/obj2yaml/elf-custom-null-section.yaml @@ -0,0 +1,143 @@ +## Check we are able to dump the SHT_NULL section at +## index 0 when it has custom section fields. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=FIRST-SEC + +# FIRST-SEC: --- !ELF +# FIRST-SEC-NEXT: FileHeader: +# FIRST-SEC-NEXT: Class: ELFCLASS64 +# FIRST-SEC-NEXT: Data: ELFDATA2LSB +# FIRST-SEC-NEXT: Type: ET_REL +# FIRST-SEC-NEXT: Machine: EM_X86_64 +# FIRST-SEC-NEXT: Sections: +# FIRST-SEC-NEXT: - Type: SHT_NULL +# FIRST-SEC-NEXT: Flags: [ SHF_ALLOC ] +# FIRST-SEC-NEXT: Address: 0x0000000000000006 +# FIRST-SEC-NEXT: Link: .foo +# FIRST-SEC-NEXT: AddressAlign: 0x0000000000000003 +# FIRST-SEC-NEXT: EntSize: 0x0000000000000005 +# FIRST-SEC-NEXT: Size: 0x0000000000000004 +# FIRST-SEC-NEXT: Info: 0x0000000000000002 +# FIRST-SEC-NEXT: - Name: .foo +# FIRST-SEC-NEXT: Type: SHT_PROGBITS +# FIRST-SEC-NEXT: ... + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Type: SHT_NULL + Name: '' + Flags: [ SHF_ALLOC ] + Link: 1 + Info: 2 + AddressAlign: 0x3 + Size: 0x4 + EntSize: 0x5 + Address: 0x6 + - Type: SHT_PROGBITS + Name: .foo + +## Check we are able to dump the SHT_NULL section at non-0 index. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=SECOND-SEC + +# SECOND-SEC: --- !ELF +# SECOND-SEC-NEXT: FileHeader: +# SECOND-SEC-NEXT: Class: ELFCLASS64 +# SECOND-SEC-NEXT: Data: ELFDATA2LSB +# SECOND-SEC-NEXT: Type: ET_REL +# SECOND-SEC-NEXT: Machine: EM_X86_64 +# SECOND-SEC-NEXT: Sections: +# SECOND-SEC-NEXT: - Name: .foo +# SECOND-SEC-NEXT: Type: SHT_PROGBITS +# SECOND-SEC-NEXT: - Type: SHT_NULL +# SECOND-SEC-NEXT: Flags: [ SHF_ALLOC ] +# SECOND-SEC-NEXT: Address: 0x0000000000000006 +# SECOND-SEC-NEXT: Link: .foo +# SECOND-SEC-NEXT: AddressAlign: 0x0000000000000003 +# SECOND-SEC-NEXT: EntSize: 0x0000000000000005 +# SECOND-SEC-NEXT: Content: '00000000' +# SECOND-SEC-NEXT: Info: 0x0000000000000002 +# SECOND-SEC-NEXT: ... + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Type: SHT_PROGBITS + Name: .foo + - Type: SHT_NULL + Name: '' + Flags: [ SHF_ALLOC ] + Link: 1 + Info: 2 + AddressAlign: 0x3 + Size: 0x4 + EntSize: 0x5 + Address: 0x6 + +## Check we do not dump the SHT_NULL section at the index 0 +## when it does not have any custom fields. + +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=NULL-SEC + +# NULL-SEC: --- !ELF +# NULL-SEC-NEXT: FileHeader: +# NULL-SEC-NEXT: Class: ELFCLASS64 +# NULL-SEC-NEXT: Data: ELFDATA2LSB +# NULL-SEC-NEXT: Type: ET_REL +# NULL-SEC-NEXT: Machine: EM_X86_64 +# NULL-SEC-NEXT: Sections: +# NULL-SEC-NEXT: - Name: .foo +# NULL-SEC-NEXT: Type: SHT_PROGBITS +# NULL-SEC-NEXT: ... + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Type: SHT_NULL + - Type: SHT_PROGBITS + Name: .foo + +## Check we dump SHT_NULL sections which are not at the begining +## of section list even if they don't have any non-null field. + +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: obj2yaml %t4 | FileCheck %s --check-prefix=NULL-SEC-MIDDLE + +# NULL-SEC-MIDDLE: --- !ELF +# NULL-SEC-MIDDLE-NEXT: FileHeader: +# NULL-SEC-MIDDLE-NEXT: Class: ELFCLASS64 +# NULL-SEC-MIDDLE-NEXT: Data: ELFDATA2LSB +# NULL-SEC-MIDDLE-NEXT: Type: ET_REL +# NULL-SEC-MIDDLE-NEXT: Machine: EM_X86_64 +# NULL-SEC-MIDDLE-NEXT: Sections: +# NULL-SEC-MIDDLE-NEXT: - Name: .foo +# NULL-SEC-MIDDLE-NEXT: Type: SHT_PROGBITS +# NULL-SEC-MIDDLE-NEXT: - Type: SHT_NULL +# NULL-SEC-MIDDLE-NEXT: ... + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Type: SHT_PROGBITS + Name: .foo + - Type: SHT_NULL Index: test/tools/obj2yaml/elf-shlink.yaml =================================================================== --- /dev/null +++ test/tools/obj2yaml/elf-shlink.yaml @@ -0,0 +1,19 @@ +## Check obj2yaml reports a proper error when unable to resolve +## a sh_link reference in a regular section. +## (We had a bug: the error was silently ignored). + +# RUN: yaml2obj %s -o %t.o +# RUN: not obj2yaml %t.o 2>&1 | FileCheck %s -DFILE=%t.o + +## CHECK: Error reading file: [[FILE]]: unable to resolve sh_link reference in section '.test': invalid section index: 42 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .test + Type: SHT_PROGBITS + Link: 42 Index: tools/obj2yaml/elf2yaml.cpp =================================================================== --- tools/obj2yaml/elf2yaml.cpp +++ tools/obj2yaml/elf2yaml.cpp @@ -176,7 +176,6 @@ Y->Sections.emplace_back(*SecOrErr); break; } - case ELF::SHT_NULL: case ELF::SHT_STRTAB: case ELF::SHT_SYMTAB: case ELF::SHT_DYNSYM: @@ -239,6 +238,18 @@ Y->Sections.emplace_back(*SecOrErr); break; } + case ELF::SHT_NULL: { + // We only dump the SHT_NULL section at index 0 when it + // has at least one non-null field, because yaml2obj + // normally creates the zero section at index 0 implicitly. + if (&Sec - &Sections[0] == 0) { + const uint8_t *Begin = reinterpret_cast(&Sec); + const uint8_t *End = Begin + sizeof(Elf_Shdr); + if (std::find_if(Begin, End, [](uint8_t V) { return V != 0; }) == End) + break; + } + LLVM_FALLTHROUGH; + } default: { Expected SecOrErr = dumpContentSection(&Sec); @@ -376,8 +387,12 @@ if (Shdr->sh_link != ELF::SHN_UNDEF) { auto LinkSection = Obj.getSection(Shdr->sh_link); - if (LinkSection.takeError()) - return LinkSection.takeError(); + if (!LinkSection) + return make_error( + "unable to resolve sh_link reference in section '" + S.Name + + "': " + toString(LinkSection.takeError()), + inconvertibleErrorCode()); + NameOrErr = getUniquedSectionName(*LinkSection); if (!NameOrErr) return NameOrErr.takeError(); @@ -467,12 +482,18 @@ if (Error E = dumpCommonSection(Shdr, *S)) return std::move(E); - auto ContentOrErr = Obj.getSectionContents(Shdr); - if (!ContentOrErr) - return ContentOrErr.takeError(); - ArrayRef Content = *ContentOrErr; - if (!Content.empty()) - S->Content = yaml::BinaryRef(Content); + unsigned SecIndex = Shdr - &Sections[0]; + if (SecIndex != 0 || Shdr->sh_type != ELF::SHT_NULL) { + auto ContentOrErr = Obj.getSectionContents(Shdr); + if (!ContentOrErr) + return ContentOrErr.takeError(); + ArrayRef Content = *ContentOrErr; + if (!Content.empty()) + S->Content = yaml::BinaryRef(Content); + } else { + S->Size = static_cast(Shdr->sh_size); + } + if (Shdr->sh_info) S->Info = static_cast(Shdr->sh_info); return S.release();