]> granicus.if.org Git - llvm/commitdiff
[yaml2obj] - Allow setting st_value explicitly for Symbol.
authorGeorge Rimar <grimar@accesssoftek.com>
Tue, 7 May 2019 12:10:51 +0000 (12:10 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Tue, 7 May 2019 12:10:51 +0000 (12:10 +0000)
In some cases it is useful to explicitly set symbol's st_name value.
For example, I am using it in a patch for LLD to remove the broken
binary from a test case and replace it with a YAML test.

Differential revision: https://reviews.llvm.org/D61180

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360137 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ObjectYAML/ELFYAML.h
lib/ObjectYAML/ELFYAML.cpp
test/tools/yaml2obj/symbol-name.yaml [new file with mode: 0644]
tools/yaml2obj/yaml2elf.cpp

index 5eb53dac542004056889959cbe6c7847275355b3..2cc71f8c53becf93cf01ea35edf09486a86356ca 100644 (file)
@@ -95,6 +95,7 @@ struct ProgramHeader {
 
 struct Symbol {
   StringRef Name;
+  Optional<uint32_t> NameIndex;
   ELF_STT Type;
   StringRef Section;
   Optional<ELF_SHN> Index;
index 93d309cdc05c0a439b4c0ceb985d0fa492e5462e..1ac624fe958f409b4beabd59ba6a65c79d5a4b77 100644 (file)
@@ -854,6 +854,7 @@ struct NormalizedOther {
 
 void MappingTraits<ELFYAML::Symbol>::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 @@ void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) {
 
 StringRef MappingTraits<ELFYAML::Symbol>::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();
 }
 
diff --git a/test/tools/yaml2obj/symbol-name.yaml b/test/tools/yaml2obj/symbol-name.yaml
new file mode 100644 (file)
index 0000000..06815b4
--- /dev/null
@@ -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 574e5dbf0f1649153c16243bdbc0f2430352398b..48da02688de6dbbd5eedfba10f3020a56e04ce25 100644 (file)
@@ -57,34 +57,34 @@ public:
 } // 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.\r
-namespace {\r
-class NameToIdxMap {\r
+// sections and symbols can be referenced by name instead of by index.
+namespace {
+class NameToIdxMap {
   StringMap<unsigned> Map;\r
 \r
-public:\r
+public:
   /// \Returns false if name is already present in the map.\r
   bool addName(StringRef Name, unsigned Ndx) {\r
     return Map.insert({Name, Ndx}).second;\r
-  }\r
+  }
   /// \Returns false if name is not present in the map.\r
-  bool lookup(StringRef Name, unsigned &Idx) const {\r
+  bool lookup(StringRef Name, unsigned &Idx) const {
     auto I = Map.find(Name);\r
-    if (I == Map.end())\r
+    if (I == Map.end())
       return false;\r
-    Idx = I->getValue();\r
+    Idx = I->getValue();
     return true;\r
-  }\r
+  }
   /// Asserts if name is not present in the map.\r
-  unsigned get(StringRef Name) const {\r
+  unsigned get(StringRef Name) const {
     unsigned Idx;\r
     if (lookup(Name, Idx))\r
       return Idx;\r
     assert(false && "Expected section not found in index");\r
     return 0;\r
-  }\r
-  unsigned size() const { return Map.size(); }\r
-};\r
+  }
+  unsigned size() const { return Map.size(); }
+};
 } // end anonymous namespace
 
 template <class T>
@@ -236,13 +236,13 @@ void ELFState<ELFT>::initProgramHeaders(std::vector<Elf_Phdr> &PHeaders) {
     PHeaders.push_back(Phdr);
   }
 }
-\r
-static bool convertSectionIndex(NameToIdxMap &SN2I, StringRef SecName,\r
-                                StringRef IndexSrc, unsigned &IndexDest) {\r
+
+static bool convertSectionIndex(NameToIdxMap &SN2I, StringRef SecName,
+                                StringRef IndexSrc, unsigned &IndexDest) {
   if (!SN2I.lookup(IndexSrc, IndexDest) && !to_integer(IndexSrc, IndexDest)) {\r
-    WithColor::error() << "Unknown section referenced: '" << IndexSrc\r
-                       << "' at YAML section '" << SecName << "'.\n";\r
-    return false;\r
+    WithColor::error() << "Unknown section referenced: '" << IndexSrc
+                       << "' at YAML section '" << SecName << "'.\n";
+    return false;
   }
   return true;
 }
@@ -468,15 +468,22 @@ void ELFState<ELFT>::addSymbols(ArrayRef<ELFYAML::Symbol> Symbols,
   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);\r
-    if (!Sym.Section.empty()) {\r
-      unsigned Index;\r
+
+    Symbol.setBindingAndType(Sym.Binding, Sym.Type);
+    if (!Sym.Section.empty()) {
+      unsigned Index;
       if (!SN2I.lookup(Sym.Section, Index)) {\r
-        WithColor::error() << "Unknown section referenced: '" << Sym.Section\r
-                           << "' by YAML symbol " << Sym.Name << ".\n";\r
-        exit(1);\r
+        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 @@ ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
   auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
 
   for (const auto &Rel : Section.Relocations) {
-    unsigned SymIdx = 0;\r
-    // If a relocation references a symbol, try to look one up in the symbol\r
-    // table. If it is not there, treat the value as a symbol index.\r
+    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) &&\r
-        !to_integer(*Rel.Symbol, SymIdx)) {\r
-      WithColor::error() << "Unknown symbol referenced: '" << *Rel.Symbol\r
-                         << "' at YAML section '" << Section.Name << "'.\n";\r
+        !to_integer(*Rel.Symbol, SymIdx)) {
+      WithColor::error() << "Unknown symbol referenced: '" << *Rel.Symbol
+                         << "' at YAML section '" << Section.Name << "'.\n";
       return false;
     }
 
@@ -580,8 +587,8 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
          "Section type is not SHT_GROUP");
 
   SHeader.sh_entsize = 4;
-  SHeader.sh_size = SHeader.sh_entsize * Section.Members.size();\r
-\r
+  SHeader.sh_size = SHeader.sh_entsize * Section.Members.size();
+
   unsigned SymIdx;\r
   if (!SymN2I.lookup(Section.Signature, SymIdx) &&\r
       !to_integer(Section.Signature, SymIdx)) {\r
@@ -781,13 +788,13 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
 
 template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
   for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
-    StringRef Name = Doc.Sections[i]->Name;\r
-    DotShStrtab.add(Name);\r
-    // "+ 1" to take into account the SHT_NULL entry.\r
+    StringRef Name = Doc.Sections[i]->Name;
+    DotShStrtab.add(Name);
+    // "+ 1" to take into account the SHT_NULL entry.
     if (!SN2I.addName(Name, i + 1)) {\r
-      WithColor::error() << "Repeated section name: '" << Name\r
-                         << "' at YAML section number " << i << ".\n";\r
-      return false;\r
+      WithColor::error() << "Repeated section name: '" << Name
+                         << "' at YAML section number " << i << ".\n";
+      return false;
     }
   }
 
@@ -817,13 +824,13 @@ bool ELFState<ELFT>::buildSymbolIndex(ArrayRef<ELFYAML::Symbol> Symbols) {
                                 "' after global in Symbols list.\n";
       return false;
     }
-    if (Sym.Binding.value != ELF::STB_LOCAL)\r
-      GlobalSymbolSeen = true;\r
-\r
+    if (Sym.Binding.value != ELF::STB_LOCAL)
+      GlobalSymbolSeen = true;
+
     if (!Name.empty() && !SymN2I.addName(Name, I)) {\r
-      WithColor::error() << "Repeated symbol name: '" << Name << "'.\n";\r
-      return false;\r
-    }\r
+      WithColor::error() << "Repeated symbol name: '" << Name << "'.\n";
+      return false;
+    }
   }
   return true;
 }