From: Rafael Espindola Date: Tue, 5 Sep 2017 22:30:00 +0000 (+0000) Subject: obj2yaml: Print unique section names. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ef318e5ebe6b4110c57c3458900fb516622c4cb7;p=llvm obj2yaml: Print unique section names. Without this patch passing a .o file with multiple sections with the same name to obj2yaml produces a yaml file that yaml2obj cannot handle. This is pr34162. The problem is that when specifying, for example, the section of a symbol, we get only Section: foo and don't know which of the sections whose name is foo we have to use. One alternative would be to use section numbers. This would work, but the output from obj2yaml would be very inconvenient to edit as deleting a section would invalidate all indexes. Another alternative would be to invent a unique section id that would exist only on yaml. This would work, but seems a bit heavy handed. We could make the id optional and default it to the section name. Since in the last alternative the id is basically what this patch uses as a name, it can be implemented as a followup patch if needed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312585 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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;