Add support to properly reference private symbols on relocation entries.
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Sat, 18 Jul 2009 19:30:09 +0000 (19:30 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Sat, 18 Jul 2009 19:30:09 +0000 (19:30 +0000)
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

include/llvm/Target/TargetELFWriterInfo.h
lib/CodeGen/ELF.h
lib/CodeGen/ELFCodeEmitter.cpp
lib/CodeGen/ELFWriter.cpp
lib/CodeGen/ELFWriter.h
lib/Target/X86/X86ELFWriterInfo.cpp
lib/Target/X86/X86ELFWriterInfo.h

index a5b30c4f6e3d6db8a7f0deed5f78dbeb9ac0a149..dbcffe0ca64f72efa988f63e6e8637b88285779b 100644 (file)
@@ -99,7 +99,14 @@ namespace llvm {
 
     /// getAddendForRelTy - Gets the addend value for an ELF relocation entry
     /// based on the target relocation type. If addend is not used returns 0.
-    virtual long int getAddendForRelTy(unsigned RelTy) const = 0;
+    virtual long int getDefaultAddendForRelTy(unsigned RelTy) const = 0;
+
+    /// getRelTySize - Returns the size of relocatable field in bits
+    virtual unsigned getRelocationTySize(unsigned RelTy) const = 0;
+
+    /// getJumpTableRelocationTy - Returns the machine relocation type used
+    /// to reference a jumptable.
+    virtual unsigned getJumpTableMachineRelocationTy() const = 0;
   };
 
 } // end llvm namespace
index 8bbb29c7bc12fc7467b67b724a032f5f7950ee50..d4dc151494c22a51df15eab41dac0ee5182ba500 100644 (file)
@@ -184,6 +184,13 @@ namespace llvm {
     /// 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) {}
index 1d150032c399e8f9252f4a7d2a643adf6f1e5035..6e6ba8ec6ac24c45bf18439fc3fd4dadc5ec022d 100644 (file)
@@ -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 @@ void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) {
          "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 @@ void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) {
     // 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
index 3e1645b2c341ef54b2dd29d6d642c79218662412..69220f9aeaad9155d68834ee58d27b375017c781 100644 (file)
@@ -296,8 +296,16 @@ void ELFWriter::EmitGlobal(const GlobalValue *GV) {
     }
   }
 
-  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 @@ bool ELFWriter::doFinalization(Module &M) {
   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 @@ void ELFWriter::EmitRelocations() {
          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 @@ void ELFWriter::EmitRelocations() {
       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);
index ee5a856ac223998925bba83a0c8449ff218a4f0f..89ab00c397dbe3e7e4599b395294e04681bb623b 100644 (file)
@@ -107,8 +107,8 @@ namespace llvm {
     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 @@ namespace llvm {
     /// 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.
index 2736a81cdd5907a5f6b78929d0f10cd882917106..4002e265304fb547ab842a8be17475f27af8366a 100644 (file)
@@ -43,7 +43,7 @@ unsigned X86ELFWriterInfo::getRelocationType(unsigned MachineRelTy) const {
       return R_X86_64_64;
     case X86::reloc_picrel_word:
     default:
-      llvm_unreachable("unknown relocation type");
+      llvm_unreachable("unknown x86_64 machine relocation type");
     }
   } else {
     switch(MachineRelTy) {
@@ -54,22 +54,55 @@ unsigned X86ELFWriterInfo::getRelocationType(unsigned MachineRelTy) const {
     case X86::reloc_absolute_dword:
     case X86::reloc_picrel_word:
     default:
-      llvm_unreachable("unknown relocation type");
+      llvm_unreachable("unknown x86 machine relocation type");
     }
   }
   return 0;
 }
 
-long int X86ELFWriterInfo::getAddendForRelTy(unsigned RelTy) const {
+long int X86ELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy) const {
   if (is64Bit) {
     switch(RelTy) {
     case R_X86_64_PC32: return -4;
-      break;
     case R_X86_64_32: return 0;
-      break;
+    default:
+      llvm_unreachable("unknown x86_64 relocation type");
+    }
+  } else {
+    switch(RelTy) {
+      case R_386_PC32: return -4;
+      case R_386_32: return 0;
+    default:
+      llvm_unreachable("unknown x86 relocation type");
+    }
+  }
+  return 0;
+}
+
+unsigned X86ELFWriterInfo::getRelocationTySize(unsigned RelTy) const {
+  if (is64Bit) {
+    switch(RelTy) {
+      case R_X86_64_PC32:
+      case R_X86_64_32:
+        return 32;
+      case R_X86_64_64:
+        return 64;
+    default:
+      llvm_unreachable("unknown x86_64 relocation type");
+    }
+  } else {
+    switch(RelTy) {
+      case R_386_PC32:
+      case R_386_32:
+        return 32;
     default:
       llvm_unreachable("unknown x86 relocation type");
     }
   }
   return 0;
 }
+
+unsigned X86ELFWriterInfo::getJumpTableMachineRelocationTy() const {
+  return X86::reloc_absolute_dword;
+}
+
index 2ba1a0bd70a23c5cf17ee4598a6fe89cf3ae9ad4..f372658f706c7b3d13c4443eb3c091cf13759bfc 100644 (file)
@@ -51,7 +51,14 @@ namespace llvm {
 
     /// getAddendForRelTy - Gets the addend value for an ELF relocation entry
     /// based on the target relocation type
-    virtual long int getAddendForRelTy(unsigned RelTy) const;
+    virtual long int getDefaultAddendForRelTy(unsigned RelTy) const;
+
+    /// getRelTySize - Returns the size of relocatable field in bits
+    virtual unsigned getRelocationTySize(unsigned RelTy) const;
+
+    /// getJumpTableRelocationTy - Returns the machine relocation type used
+    /// to reference a jumptable.
+    virtual unsigned getJumpTableMachineRelocationTy() const;
   };
 
 } // end llvm namespace