Index: llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h +++ llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h @@ -95,6 +95,7 @@ struct Symbol { StringRef Name; + Optional NameIndex; ELF_STT Type; StringRef Section; Optional Index; Index: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp =================================================================== --- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp +++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp @@ -854,6 +854,7 @@ void MappingTraits::mapping(IO &IO, ELFYAML::Symbol &Symbol) { IO.mapOptional("Name", Symbol.Name, StringRef()); + IO.mapOptional("NameIndex", Symbol.NameIndex); IO.mapOptional("Type", Symbol.Type, ELFYAML::ELF_STT(0)); IO.mapOptional("Section", Symbol.Section, StringRef()); IO.mapOptional("Index", Symbol.Index); @@ -867,12 +868,12 @@ StringRef MappingTraits::validate(IO &IO, ELFYAML::Symbol &Symbol) { - if (Symbol.Index && Symbol.Section.data()) { + if (Symbol.Index && Symbol.Section.data()) return "Index and Section cannot both be specified for Symbol"; - } - if (Symbol.Index && *Symbol.Index == ELFYAML::ELF_SHN(ELF::SHN_XINDEX)) { + if (Symbol.Index && *Symbol.Index == ELFYAML::ELF_SHN(ELF::SHN_XINDEX)) return "Large indexes are not supported"; - } + if (Symbol.NameIndex && !Symbol.Name.empty()) + return "Name and NameIndex cannot both be specified for Symbol"; return StringRef(); } Index: llvm/trunk/test/tools/yaml2obj/symbol-name.yaml =================================================================== --- llvm/trunk/test/tools/yaml2obj/symbol-name.yaml +++ llvm/trunk/test/tools/yaml2obj/symbol-name.yaml @@ -0,0 +1,37 @@ +## Check we are able to use integers as both +## symbol name indices (st_name values) and symbol names. +# RUN: yaml2obj --docnum=1 %s > %t +# RUN: llvm-readobj --symbols %t | FileCheck %s + +# CHECK: Name: test (1) +# CHECK: Name: test (1) +# CHECK: Name: est (2) +# CHECK: Name: 1 (8) +# CHECK: Name: 2 (6) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Symbols: + - Name: test + - NameIndex: 1 + - NameIndex: 2 + - Name: 1 + - Name: 2 + +## Check we do not allow specifying both Name and NameIndex at once. +# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=ERR +# ERR: error: Name and NameIndex cannot both be specified for Symbol + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Symbols: + - Name: foo + NameIndex: 0 Index: llvm/trunk/tools/yaml2obj/yaml2elf.cpp =================================================================== --- llvm/trunk/tools/yaml2obj/yaml2elf.cpp +++ llvm/trunk/tools/yaml2obj/yaml2elf.cpp @@ -57,34 +57,34 @@ } // end anonymous namespace // Used to keep track of section and symbol names, so that in the YAML file -// sections and symbols can be referenced by name instead of by index. -namespace { -class NameToIdxMap { +// sections and symbols can be referenced by name instead of by index. +namespace { +class NameToIdxMap { StringMap Map; -public: +public: /// \Returns false if name is already present in the map. bool addName(StringRef Name, unsigned Ndx) { return Map.insert({Name, Ndx}).second; - } + } /// \Returns false if name is not present in the map. - bool lookup(StringRef Name, unsigned &Idx) const { + bool lookup(StringRef Name, unsigned &Idx) const { auto I = Map.find(Name); - if (I == Map.end()) + if (I == Map.end()) return false; - Idx = I->getValue(); + Idx = I->getValue(); return true; - } + } /// Asserts if name is not present in the map. - unsigned get(StringRef Name) const { + unsigned get(StringRef Name) const { unsigned Idx; if (lookup(Name, Idx)) return Idx; assert(false && "Expected section not found in index"); return 0; - } - unsigned size() const { return Map.size(); } -}; + } + unsigned size() const { return Map.size(); } +}; } // end anonymous namespace template @@ -236,13 +236,13 @@ PHeaders.push_back(Phdr); } } - -static bool convertSectionIndex(NameToIdxMap &SN2I, StringRef SecName, - StringRef IndexSrc, unsigned &IndexDest) { + +static bool convertSectionIndex(NameToIdxMap &SN2I, StringRef SecName, + StringRef IndexSrc, unsigned &IndexDest) { if (!SN2I.lookup(IndexSrc, IndexDest) && !to_integer(IndexSrc, IndexDest)) { - WithColor::error() << "Unknown section referenced: '" << IndexSrc - << "' at YAML section '" << SecName << "'.\n"; - return false; + WithColor::error() << "Unknown section referenced: '" << IndexSrc + << "' at YAML section '" << SecName << "'.\n"; + return false; } return true; } @@ -468,15 +468,22 @@ for (const auto &Sym : Symbols) { Elf_Sym Symbol; zero(Symbol); - if (!Sym.Name.empty()) + + // If NameIndex, which contains the name offset, is explicitly specified, we + // use it. This is useful for preparing broken objects. Otherwise, we add + // the specified Name to the string table builder to get its offset. + if (Sym.NameIndex) + Symbol.st_name = *Sym.NameIndex; + else if (!Sym.Name.empty()) Symbol.st_name = Strtab.getOffset(Sym.Name); - Symbol.setBindingAndType(Sym.Binding, Sym.Type); - if (!Sym.Section.empty()) { - unsigned Index; + + Symbol.setBindingAndType(Sym.Binding, Sym.Type); + if (!Sym.Section.empty()) { + unsigned Index; if (!SN2I.lookup(Sym.Section, Index)) { - WithColor::error() << "Unknown section referenced: '" << Sym.Section - << "' by YAML symbol " << Sym.Name << ".\n"; - exit(1); + WithColor::error() << "Unknown section referenced: '" << Sym.Section + << "' by YAML symbol " << Sym.Name << ".\n"; + exit(1); } Symbol.st_shndx = Index; } else if (Sym.Index) { @@ -544,13 +551,13 @@ auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); for (const auto &Rel : Section.Relocations) { - unsigned SymIdx = 0; - // If a relocation references a symbol, try to look one up in the symbol - // table. If it is not there, treat the value as a symbol index. + unsigned SymIdx = 0; + // If a relocation references a symbol, try to look one up in the symbol + // table. If it is not there, treat the value as a symbol index. if (Rel.Symbol && !SymN2I.lookup(*Rel.Symbol, SymIdx) && - !to_integer(*Rel.Symbol, SymIdx)) { - WithColor::error() << "Unknown symbol referenced: '" << *Rel.Symbol - << "' at YAML section '" << Section.Name << "'.\n"; + !to_integer(*Rel.Symbol, SymIdx)) { + WithColor::error() << "Unknown symbol referenced: '" << *Rel.Symbol + << "' at YAML section '" << Section.Name << "'.\n"; return false; } @@ -580,8 +587,8 @@ "Section type is not SHT_GROUP"); SHeader.sh_entsize = 4; - SHeader.sh_size = SHeader.sh_entsize * Section.Members.size(); - + SHeader.sh_size = SHeader.sh_entsize * Section.Members.size(); + unsigned SymIdx; if (!SymN2I.lookup(Section.Signature, SymIdx) && !to_integer(Section.Signature, SymIdx)) { @@ -781,13 +788,13 @@ template bool ELFState::buildSectionIndex() { for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) { - StringRef Name = Doc.Sections[i]->Name; - DotShStrtab.add(Name); - // "+ 1" to take into account the SHT_NULL entry. + StringRef Name = Doc.Sections[i]->Name; + DotShStrtab.add(Name); + // "+ 1" to take into account the SHT_NULL entry. if (!SN2I.addName(Name, i + 1)) { - WithColor::error() << "Repeated section name: '" << Name - << "' at YAML section number " << i << ".\n"; - return false; + WithColor::error() << "Repeated section name: '" << Name + << "' at YAML section number " << i << ".\n"; + return false; } } @@ -817,13 +824,13 @@ "' after global in Symbols list.\n"; return false; } - if (Sym.Binding.value != ELF::STB_LOCAL) - GlobalSymbolSeen = true; - + if (Sym.Binding.value != ELF::STB_LOCAL) + GlobalSymbolSeen = true; + if (!Name.empty() && !SymN2I.addName(Name, I)) { - WithColor::error() << "Repeated symbol name: '" << Name << "'.\n"; - return false; - } + WithColor::error() << "Repeated symbol name: '" << Name << "'.\n"; + return false; + } } return true; }