Index: test/Object/X86/obj2yaml-dup-section-name.s =================================================================== --- test/Object/X86/obj2yaml-dup-section-name.s +++ test/Object/X86/obj2yaml-dup-section-name.s @@ -9,16 +9,16 @@ # CHECK: - Name: .text.foo{{$}} # CHECK: - Name: .rela.text.foo{{$}} # CHECK: Info: .text.foo{{$}} -# CHECK: - Name: .group1{{$}} +# CHECK: - Name: '.group [1]' # 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: - SectionOrType: '.text.foo [2]' +# CHECK: - SectionOrType: '.rela.text.foo [3]' +# CHECK: - Name: '.text.foo [2]' +# CHECK: - Name: '.rela.text.foo [3]' +# CHECK: Info: '.text.foo [2]' # CHECK: Symbols: # CHECK: Section: .group{{$}} -# CHECK: Section: .group1{{$}} +# CHECK: Section: '.group [1]' .section .text.foo,"axG",@progbits,sym1,comdat Index: test/tools/obj2yaml/duplicate-symbol-names.test =================================================================== --- /dev/null +++ test/tools/obj2yaml/duplicate-symbol-names.test @@ -0,0 +1,45 @@ +## Check that obj2yaml is able to produce the YAML +## from the object containing symbols with duplicate names. + +# RUN: yaml2obj %s -o %t1 +# RUN: llvm-readobj -t %t1 | FileCheck %s + +# CHECK: Name: localfoo (1) +# CHECK: Name: localfoo (1) + +# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=YAML + +# YAML: --- !ELF +# YAML-NEXT: FileHeader: +# YAML-NEXT: Class: ELFCLASS64 +# YAML-NEXT: Data: ELFDATA2LSB +# YAML-NEXT: Type: ET_REL +# YAML-NEXT: Machine: EM_X86_64 +# YAML-NEXT: Sections: +# YAML-NEXT: - Name: .text.foo.1 +# YAML-NEXT: Type: SHT_PROGBITS +# YAML-NEXT: - Name: .text.foo.2 +# YAML-NEXT: Type: SHT_PROGBITS +# YAML-NEXT: Symbols: +# YAML-NEXT: - Name: localfoo +# YAML-NEXT: Section: .text.foo.1 +# YAML-NEXT: - Name: 'localfoo [1]' +# YAML-NEXT: Section: .text.foo.2 +# YAML-NEXT: ... + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text.foo.1 + Type: SHT_PROGBITS + - Name: .text.foo.2 + Type: SHT_PROGBITS +Symbols: + - Name: 'localfoo [111]' + Section: .text.foo.1 + - Name: 'localfoo [222]' + Section: .text.foo.2 Index: test/tools/yaml2obj/duplicate-section-names.test =================================================================== --- /dev/null +++ test/tools/yaml2obj/duplicate-section-names.test @@ -0,0 +1,63 @@ +## Check that yaml2obj is able to produce an object from the YAML +## containing section with duplicate names (but different name suffixes). + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readobj -s %t1 | FileCheck %s --check-prefix=CASE1 + +# CASE1: Name: .foo1 ( +# CASE1: Name: .foo ( +# CASE1: Name: .foo ( +# CASE1: Name: .foo2 ( + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo1 + Type: SHT_PROGBITS + - Name: .foo + Type: SHT_PROGBITS + - Name: '.foo [1]' + Type: SHT_PROGBITS + - Name: .foo2 + Type: SHT_PROGBITS + +## Check that yaml2obj reports an error in case we have +## sections with equal names and suffixes. + +# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=CASE2 +# CASE2: error: Repeated section name: '.foo [1]' at YAML section number 1. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: '.foo [1]' + Type: SHT_PROGBITS + - Name: '.foo [1]' + Type: SHT_PROGBITS + +## Check that yaml2obj reports an error in case we have +## symbols without suffixes in the names and their +## names are equal. + +# RUN: not yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --check-prefix=CASE3 +# CASE3: error: Repeated section name: '.foo' at YAML section number 1. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + - Name: .foo + Type: SHT_PROGBITS Index: test/tools/yaml2obj/duplicate-symbol-names.test =================================================================== --- /dev/null +++ test/tools/yaml2obj/duplicate-symbol-names.test @@ -0,0 +1,53 @@ +## Check that yaml2obj is able to produce an object from the YAML +## containing symbols with duplicate names (but different name suffixes). + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readobj -t %t1 | FileCheck %s --check-prefix=CASE1 + +# CASE1: Name: localfoo (1) +# CASE1: Name: localfoo (1) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Symbols: + - Name: localfoo + - Name: 'localfoo [1]' + +## Check that yaml2obj reports an error in case we have +## symbols with equal names and suffixes. + +# RUN: not yaml2obj --docnum=2 %s 2>&1| FileCheck %s --check-prefix=CASE2 +# CASE2: error: Repeated symbol name: 'localfoo [1]'. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Symbols: + - Name: 'localfoo [1]' + - Name: 'localfoo [1]' + +## Check that yaml2obj reports an error in case we have +## symbols without suffixes in the names and their +## names are equal. + +# RUN: not yaml2obj --docnum=3 %s 2>&1| FileCheck %s --check-prefix=CASE3 +# CASE3: error: Repeated symbol name: 'localfoo'. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Symbols: + - Name: localfoo + Section: .text.foo.1 + - Name: localfoo + Section: .text.foo.2 Index: tools/obj2yaml/elf2yaml.cpp =================================================================== --- tools/obj2yaml/elf2yaml.cpp +++ tools/obj2yaml/elf2yaml.cpp @@ -14,6 +14,8 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/YAMLTraits.h" +#include + using namespace llvm; namespace { @@ -29,14 +31,19 @@ ArrayRef Sections; - // If the file has multiple sections with the same name, we add a - // suffix to make them unique. + // If the file has multiple sections or symbols with the same name, + // we add a special suffix to make them unique. unsigned Suffix = 0; + DenseSet UsedSectionNames; std::vector SectionNames; + + DenseSet UsedSymbolNames; + std::vector> UniquedSymbolNames; + Expected getUniquedSectionName(const Elf_Shdr *Sec); Expected getSymbolName(const Elf_Sym *Sym, StringRef StrTable, - const Elf_Shdr *SymTab); + const Elf_Shdr *SymTab, bool Uniquify); const object::ELFFile &Obj; ArrayRef ShndxTable; @@ -87,16 +94,17 @@ return NameOrErr; StringRef Name = *NameOrErr; std::string &Ret = SectionNames[SecIndex]; - Ret = Name; - while (!UsedSectionNames.insert(Ret).second) - Ret = (Name + to_string(++Suffix)).str(); + if (!UsedSectionNames.insert(Name).second) + Ret = (Name + " [" + to_string(++Suffix) + "]").str(); + else + Ret = Name; return Ret; } template -Expected ELFDumper::getSymbolName(const Elf_Sym *Sym, - StringRef StrTable, - const Elf_Shdr *SymTab) { +Expected +ELFDumper::getSymbolName(const Elf_Sym *Sym, StringRef StrTable, + const Elf_Shdr *SymTab, bool Uniquify) { Expected SymbolNameOrErr = Sym->getName(StrTable); if (!SymbolNameOrErr) return SymbolNameOrErr; @@ -107,7 +115,13 @@ return ShdrOrErr.takeError(); return getUniquedSectionName(*ShdrOrErr); } - return Name; + + if (!Uniquify || UsedSymbolNames.insert(Name).second) + return Name; + + UniquedSymbolNames.push_back(llvm::make_unique( + (Name + " [" + to_string(++Suffix) + "]").str())); + return *UniquedSymbolNames.back().get(); } template ErrorOr ELFDumper::dump() { @@ -261,7 +275,8 @@ S.Other = Sym->st_other; S.Binding = Sym->getBinding(); - Expected SymbolNameOrErr = getSymbolName(Sym, StrTable, SymTab); + Expected SymbolNameOrErr = + getSymbolName(Sym, StrTable, SymTab, true /*Uniquify*/); if (!SymbolNameOrErr) return errorToErrorCode(SymbolNameOrErr.takeError()); S.Name = SymbolNameOrErr.get(); @@ -310,7 +325,8 @@ StringRef StrTab = *StrTabOrErr; if (Sym) { - Expected NameOrErr = getSymbolName(Sym, StrTab, SymTab); + Expected NameOrErr = + getSymbolName(Sym, StrTab, SymTab, false /*Uniquify*/); if (!NameOrErr) return errorToErrorCode(NameOrErr.takeError()); R.Symbol = NameOrErr.get(); @@ -603,7 +619,7 @@ return errorToErrorCode(StrTabOrErr.takeError()); Expected SymbolName = - getSymbolName(*SymOrErr, *StrTabOrErr, Symtab); + getSymbolName(*SymOrErr, *StrTabOrErr, Symtab, false /*Uniquify*/); if (!SymbolName) return errorToErrorCode(SymbolName.takeError()); S->Signature = *SymbolName; Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -268,6 +268,13 @@ return true; } +static StringRef dropUniqueSuffix(StringRef S) { + size_t SuffixPos = S.rfind(" ["); + if (SuffixPos == StringRef::npos) + return S; + return S.slice(0, SuffixPos); +} + template bool ELFState::initSectionHeaders(ELFState &State, std::vector &SHeaders, @@ -301,7 +308,7 @@ assert(Sec && "It can't be null unless it is an implicit section. But all " "implicit sections should already have been handled above."); - SHeader.sh_name = DotShStrtab.getOffset(SecName); + SHeader.sh_name = DotShStrtab.getOffset(dropUniqueSuffix(SecName)); SHeader.sh_type = Sec->Type; if (Sec->Flags) SHeader.sh_flags = *Sec->Flags; @@ -591,7 +598,7 @@ if (Sym.NameIndex) Symbol.st_name = *Sym.NameIndex; else if (!Sym.Name.empty()) - Symbol.st_name = Strtab.getOffset(Sym.Name); + Symbol.st_name = Strtab.getOffset(dropUniqueSuffix(Sym.Name)); Symbol.setBindingAndType(Sym.Binding, Sym.Type); if (!Sym.Section.empty()) { @@ -904,7 +911,7 @@ template bool ELFState::buildSectionIndex() { for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) { StringRef Name = Doc.Sections[i]->Name; - DotShStrtab.add(Name); + DotShStrtab.add(dropUniqueSuffix(Name)); // "+ 1" to take into account the SHT_NULL entry. if (!SN2I.addName(Name, i + 1)) { WithColor::error() << "Repeated section name: '" << Name @@ -953,12 +960,12 @@ template void ELFState::finalizeStrings() { // Add the regular symbol names to .strtab section. for (const ELFYAML::Symbol &Sym : Doc.Symbols) - DotStrtab.add(Sym.Name); + DotStrtab.add(dropUniqueSuffix(Sym.Name)); DotStrtab.finalize(); // Add the dynamic symbol names to .dynstr section. for (const ELFYAML::Symbol &Sym : Doc.DynamicSymbols) - DotDynstr.add(Sym.Name); + DotDynstr.add(dropUniqueSuffix(Sym.Name)); // SHT_GNU_verdef and SHT_GNU_verneed sections might also // add strings to .dynstr section.