[yaml2obj] - Allow setting st_value explicitly for Symbol.

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

llvm-svn: 360137
diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp
index 574e5db..48da026 100644
--- a/llvm/tools/yaml2obj/yaml2elf.cpp
+++ b/llvm/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<unsigned> 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 <class T>
@@ -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 <class ELFT> bool ELFState<ELFT>::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;
 }