Add support to properly reference private symbols on relocation entries.
Use proper relocation type to build relocations for JumpTables (rodata
sections).


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76326 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h
index 8bbb29c..d4dc151 100644
--- a/lib/CodeGen/ELF.h
+++ b/lib/CodeGen/ELF.h
@@ -184,6 +184,13 @@
     /// Sym - The symbol to represent this section if it has one.
     ELFSym *Sym;
 
+    /// getSymIndex - Returns the symbol table index of the symbol
+    /// representing this section.
+    unsigned getSymbolTableIndex() const {
+      assert(Sym && "section not present in the symbol table");
+      return Sym->SymTabIdx;
+    }
+
     ELFSection(const std::string &name, bool isLittleEndian, bool is64Bit)
       : BinaryObject(name, isLittleEndian, is64Bit), Type(0), Flags(0), Addr(0),
         Offset(0), Size(0), Link(0), Info(0), Align(0), EntSize(0), Sym(0) {}
diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp
index 1d15003..6e6ba8e 100644
--- a/lib/CodeGen/ELFCodeEmitter.cpp
+++ b/lib/CodeGen/ELFCodeEmitter.cpp
@@ -20,6 +20,7 @@
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/CodeGen/MachineRelocation.h"
 #include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetELFWriterInfo.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Support/Debug.h"
@@ -160,6 +161,7 @@
          "PIC codegen not yet handled for elf jump tables!");
 
   const TargetAsmInfo *TAI = TM.getTargetAsmInfo();
+  const TargetELFWriterInfo *TEW = TM.getELFWriterInfo();
 
   // Get the ELF Section to emit the jump table
   unsigned Align = TM.getTargetData()->getPointerABIAlignment();
@@ -183,9 +185,10 @@
     // Each MBB entry in the Jump table section has a relocation entry
     // against the current text section.
     for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) {
+      unsigned MachineRelTy = TEW->getJumpTableMachineRelocationTy();
       MachineRelocation MR =
         MachineRelocation::getBB(JTSection.size(),
-                                 MachineRelocation::VANILLA,
+                                 MachineRelTy,
                                  MBBs[mi]);
 
       // Offset of JT 'i' in JT section
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index 3e1645b..69220f9 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -296,8 +296,16 @@
     }
   }
 
-  if (!GV->hasPrivateLinkage())
+  // Private symbols must never go to the symbol table.
+  unsigned SymIdx = 0;
+  if (GV->hasPrivateLinkage()) {
+    PrivateSyms.push_back(GblSym);
+    SymIdx = PrivateSyms.size()-1;
+  } else {
     SymbolList.push_back(GblSym);
+  }
+
+  GblSymLookup[GV] = SymIdx;
 }
 
 void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
@@ -394,20 +402,16 @@
   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
        I != E; ++I) {
     EmitGlobal(I);
-    GblSymLookup[I] = 0;
   }
 
   // Emit all pending globals
   // TODO: this should be done only for referenced symbols
   for (SetVector<GlobalValue*>::const_iterator I = PendingGlobals.begin(),
        E = PendingGlobals.end(); I != E; ++I) {
-
     // No need to emit the symbol again
     if (GblSymLookup.find(*I) != GblSymLookup.end())
       continue;
-
     EmitGlobal(*I);
-    GblSymLookup[*I] = 0;
   }
 
   // Emit non-executable stack note
@@ -480,7 +484,8 @@
          MRE = Relos.end(); MRI != MRE; ++MRI) {
       MachineRelocation &MR = *MRI;
 
-      // Offset from the start of the section containing the symbol
+      // Holds the relocatable field address as an offset from the
+      // beginning of the section where it lives
       unsigned Offset = MR.getMachineCodeOffset();
 
       // Symbol index in the symbol table
@@ -498,15 +503,34 @@
       if (MR.isGlobalValue()) {
         const GlobalValue *G = MR.getGlobalValue();
         SymIdx = GblSymLookup[G];
-        Addend = TEW->getAddendForRelTy(RelType);
+        if (G->hasPrivateLinkage()) {
+          // If the target uses a section offset in the relocation:
+          // SymIdx + Addend = section sym for global + section offset
+          unsigned SectionIdx = PrivateSyms[SymIdx]->SectionIdx;
+          Addend = PrivateSyms[SymIdx]->Value;
+          SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();
+        } else {
+          Addend = TEW->getDefaultAddendForRelTy(RelType);
+        }
       } else {
         // Get the symbol index for the section symbol referenced
         // by the relocation
         unsigned SectionIdx = MR.getConstantVal();
-        SymIdx = SectionList[SectionIdx]->Sym->SymTabIdx;
+        SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();
         Addend = (uint64_t)MR.getResultPointer();
       }
 
+      // The target without addend on the relocation symbol must be
+      // patched in the relocation place itself to contain the addend
+      if (!HasRelA) {
+        if (TEW->getRelocationTySize(RelType) == 32)
+          S.fixWord32(Addend, Offset);
+        else if (TEW->getRelocationTySize(RelType) == 64)
+          S.fixWord64(Addend, Offset);
+        else
+          llvm_unreachable("don't know howto patch relocatable field");
+      }
+
       // Get the relocation entry and emit to the relocation section
       ELFRelocation Rel(Offset, SymIdx, RelType, HasRelA, Addend);
       EmitRelocation(RelSec, Rel, HasRelA);
diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h
index ee5a856..89ab00c 100644
--- a/lib/CodeGen/ELFWriter.h
+++ b/lib/CodeGen/ELFWriter.h
@@ -107,8 +107,8 @@
     std::map<std::string, ELFSection*> SectionLookup;
 
     /// GblSymLookup - This is a mapping from global value to a symbol index
-    /// in the symbol table. This is useful since relocations symbol references
-    /// must be quickly mapped to a symbol table index
+    /// in the symbol table or private symbols list. This is useful since reloc
+    /// symbol references must be quickly mapped to their indices on the lists
     std::map<const GlobalValue*, uint32_t> GblSymLookup;
 
     /// SymbolList - This is the list of symbols emitted to the symbol table.
@@ -116,6 +116,10 @@
     /// the beginning while non-locals at the end.
     std::vector<ELFSym*> SymbolList;
 
+    /// PrivateSyms - Record private symbols, every symbol here must never be
+    /// present in the SymbolList.
+    std::vector<ELFSym*> PrivateSyms;
+
     /// PendingGlobals - List of externally defined symbols that we have been
     /// asked to emit, but have not seen a reference to.  When a reference
     /// is seen, the symbol will move from this list to the SymbolList.