diff --git a/test/Object/X86/obj2yaml-dup-section-name.s b/test/Object/X86/obj2yaml-dup-section-name.s new file mode 100644 index 00000000000..a02e93fa54a --- /dev/null +++ b/test/Object/X86/obj2yaml-dup-section-name.s @@ -0,0 +1,28 @@ +# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux +# RUN: obj2yaml %t.o | FileCheck %s + +# CHECK: Sections: +# CHECK: - Name: .group{{$}} +# CHECK: Members: +# CHECK: - SectionOrType: .text.foo{{$}} +# CHECK: - SectionOrType: .rela.text.foo{{$}} +# CHECK: - Name: .text.foo{{$}} +# CHECK: - Name: .rela.text.foo{{$}} +# CHECK: Info: .text.foo{{$}} +# CHECK: - Name: .group1{{$}} +# CHECK: Members: +# CHECK: - SectionOrType: .text.foo2{{$}} +# CHECK: - SectionOrType: .rela.text.foo3{{$}} +# CHECK: - Name: .text.foo2{{$}} +# CHECK: - Name: .rela.text.foo3{{$}} +# CHECK: Info: .text.foo2{{$}} +# CHECK: Symbols: +# CHECK: Section: .group{{$}} +# CHECK: Section: .group1{{$}} + + + .section .text.foo,"axG",@progbits,sym1,comdat + .quad undef + + .section .text.foo,"axG",@progbits,sym2,comdat + .quad undef diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp index 9f9ef99265d..3f33fbd7d68 100644 --- a/tools/obj2yaml/elf2yaml.cpp +++ b/tools/obj2yaml/elf2yaml.cpp @@ -9,6 +9,7 @@ #include "Error.h" #include "obj2yaml.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/ObjectYAML/ELFYAML.h" @@ -27,6 +28,15 @@ class ELFDumper { typedef typename object::ELFFile::Elf_Rel Elf_Rel; typedef typename object::ELFFile::Elf_Rela Elf_Rela; + ArrayRef Sections; + + // If the file has multiple sections with the same name, we add a + // suffix to make them unique. + unsigned Suffix = 0; + DenseSet UsedSectionNames; + std::vector SectionNames; + Expected getUniquedSectionName(const Elf_Shdr *Sec); + const object::ELFFile &Obj; ArrayRef ShndxTable; @@ -59,7 +69,25 @@ ELFDumper::ELFDumper(const object::ELFFile &O) : Obj(O) {} template -ErrorOr ELFDumper::dump() { +Expected +ELFDumper::getUniquedSectionName(const Elf_Shdr *Sec) { + unsigned SecIndex = Sec - &Sections[0]; + assert(&Sections[SecIndex] == Sec); + if (!SectionNames[SecIndex].empty()) + return SectionNames[SecIndex]; + + auto NameOrErr = Obj.getSectionName(Sec); + if (!NameOrErr) + return NameOrErr; + StringRef Name = *NameOrErr; + std::string Ret = Name; + while (!UsedSectionNames.insert(Ret).second) + Ret = (Name + to_string(++Suffix)).str(); + SectionNames[SecIndex] = Ret; + return SectionNames[SecIndex]; +} + +template ErrorOr ELFDumper::dump() { auto Y = make_unique(); // Dump header @@ -77,7 +105,9 @@ ErrorOr ELFDumper::dump() { auto SectionsOrErr = Obj.sections(); if (!SectionsOrErr) return errorToErrorCode(SectionsOrErr.takeError()); - for (const Elf_Shdr &Sec : *SectionsOrErr) { + Sections = *SectionsOrErr; + SectionNames.resize(Sections.size()); + for (const Elf_Shdr &Sec : Sections) { switch (Sec.sh_type) { case ELF::SHT_NULL: case ELF::SHT_DYNSYM: @@ -199,7 +229,7 @@ ELFDumper::dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab, if (!Shdr) return obj2yaml_error::success; - auto NameOrErr = Obj.getSectionName(Shdr); + auto NameOrErr = getUniquedSectionName(Shdr); if (!NameOrErr) return errorToErrorCode(NameOrErr.takeError()); S.Section = NameOrErr.get(); @@ -252,7 +282,7 @@ std::error_code ELFDumper::dumpCommonSection(const Elf_Shdr *Shdr, S.Address = Shdr->sh_addr; S.AddressAlign = Shdr->sh_addralign; - auto NameOrErr = Obj.getSectionName(Shdr); + auto NameOrErr = getUniquedSectionName(Shdr); if (!NameOrErr) return errorToErrorCode(NameOrErr.takeError()); S.Name = NameOrErr.get(); @@ -261,7 +291,7 @@ std::error_code ELFDumper::dumpCommonSection(const Elf_Shdr *Shdr, auto LinkSection = Obj.getSection(Shdr->sh_link); if (LinkSection.takeError()) return errorToErrorCode(LinkSection.takeError()); - NameOrErr = Obj.getSectionName(*LinkSection); + NameOrErr = getUniquedSectionName(*LinkSection); if (!NameOrErr) return errorToErrorCode(NameOrErr.takeError()); S.Link = NameOrErr.get(); @@ -281,7 +311,7 @@ ELFDumper::dumpCommonRelocationSection(const Elf_Shdr *Shdr, if (!InfoSection) return errorToErrorCode(InfoSection.takeError()); - auto NameOrErr = Obj.getSectionName(*InfoSection); + auto NameOrErr = getUniquedSectionName(*InfoSection); if (!NameOrErr) return errorToErrorCode(NameOrErr.takeError()); S.Info = NameOrErr.get(); @@ -410,7 +440,7 @@ ErrorOr ELFDumper::dumpGroup(const Elf_Shdr *Shdr) { auto sHdr = Obj.getSection(groupMembers[i]); if (!sHdr) return errorToErrorCode(sHdr.takeError()); - auto sectionName = Obj.getSectionName(*sHdr); + auto sectionName = getUniquedSectionName(*sHdr); if (!sectionName) return errorToErrorCode(sectionName.takeError()); s.sectionNameOrType = *sectionName;