For PC relative relocations where symbols are defined in the same section they
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Mon, 20 Jul 2009 08:52:02 +0000 (08:52 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Mon, 20 Jul 2009 08:52:02 +0000 (08:52 +0000)
are referenced, ignore the relocation entry and patch the relocatable field with
the computed symbol offset directly

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

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

index b583572cc907b6842b54043d2fda7959eaa167b6..ef3ca1c4fc4eeb05a87e90bdaa898122f4a4c3a4 100644 (file)
@@ -105,16 +105,25 @@ namespace llvm {
     /// ELF relocation entry.
     virtual bool hasRelocationAddend() const = 0;
 
-    /// getAddendForRelTy - Gets the addend value for an ELF relocation entry
-    /// based on the target relocation type. If addend is not used returns 0.
+    /// getDefaultAddendForRelTy - Gets the default addend value for a
+    /// relocation entry based on the target ELF relocation type.
     virtual long int getDefaultAddendForRelTy(unsigned RelTy) const = 0;
 
     /// getRelTySize - Returns the size of relocatable field in bits
     virtual unsigned getRelocationTySize(unsigned RelTy) const = 0;
 
+    /// isPCRelativeRel - True if the relocation type is pc relative
+    virtual bool isPCRelativeRel(unsigned RelTy) const = 0;
+
     /// getJumpTableRelocationTy - Returns the machine relocation type used
     /// to reference a jumptable.
     virtual unsigned getAbsoluteLabelMachineRelTy() const = 0;
+
+    /// computeRelocation - Some relocatable fields could be relocated
+    /// directly, avoiding the emission of a relocation symbol, compute the
+    /// final relocation value for this symbol.
+    virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset,
+                                       unsigned RelTy) const = 0;
   };
 
 } // end llvm namespace
index 527adb821e7bab79a934e2ff737dada1152c840a..f04efd5c8c77b10984d8a627b10788b345fba4e2 100644 (file)
@@ -145,7 +145,7 @@ bool ELFWriter::doInitialization(Module &M) {
   return false;
 }
 
-/// Get jump table section on the section name returned by TAI
+// Get jump table section on the section name returned by TAI
 ELFSection &ELFWriter::getJumpTableSection() {
   unsigned Align = TM.getTargetData()->getPointerABIAlignment();
   return getSection(TAI->getJumpTableDataSection(),
@@ -153,7 +153,7 @@ ELFSection &ELFWriter::getJumpTableSection() {
                     ELFSection::SHF_ALLOC, Align);
 }
 
-// Get a constant pool section based on the section name returned by TAI
+// Get a constant pool section based on the section name returned by TAI
 ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) {
   std::string CstPoolName =
     TAI->SelectSectionForMachineConst(CPE.getType())->getName();
@@ -163,6 +163,19 @@ ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) {
                     CPE.getAlignment());
 }
 
+// Return the relocation section of section 'S'. 'RelA' is true
+// if the relocation section contains entries with addends.
+ELFSection &ELFWriter::getRelocSection(ELFSection &S) {
+  unsigned SectionHeaderTy = TEW->hasRelocationAddend() ?
+                              ELFSection::SHT_RELA : ELFSection::SHT_REL;
+  std::string RelSName(".rel");
+  if (TEW->hasRelocationAddend())
+    RelSName.append("a");
+  RelSName.append(S.getName());
+
+  return getSection(RelSName, SectionHeaderTy, 0, TEW->getPrefELFAlignment());
+}
+
 // getGlobalELFVisibility - Returns the ELF specific visibility type
 unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
   switch (GV->getVisibility()) {
@@ -474,20 +487,32 @@ bool ELFWriter::doFinalization(Module &M) {
   return false;
 }
 
+// RelocateField - Patch relocatable field with 'Offset' in 'BO'
+// using a 'Value' of known 'Size'
+void ELFWriter::RelocateField(BinaryObject &BO, uint32_t Offset,
+                              int64_t Value, unsigned Size) {
+  if (Size == 32)
+    BO.fixWord32(Value, Offset);
+  else if (Size == 64)
+    BO.fixWord64(Value, Offset);
+  else
+    llvm_unreachable("don't know howto patch relocatable field");
+}
+
 /// EmitRelocations - Emit relocations
 void ELFWriter::EmitRelocations() {
 
+  // True if the target uses the relocation entry to hold the addend,
+  // otherwise the addend is written directly to the relocatable field.
+  bool HasRelA = TEW->hasRelocationAddend();
+
   // Create Relocation sections for each section which needs it.
   for (unsigned i=0, e=SectionList.size(); i != e; ++i) {
     ELFSection &S = *SectionList[i];
 
     // This section does not have relocations
     if (!S.hasRelocations()) continue;
-
-    // Get the relocation section for section 'S'
-    bool HasRelA = TEW->hasRelocationAddend();
-    ELFSection &RelSec = getRelocSection(S.getName(), HasRelA,
-                                         TEW->getPrefELFAlignment());
+    ELFSection &RelSec = getRelocSection(S);
 
     // 'Link' - Section hdr idx of the associated symbol table
     // 'Info' - Section hdr idx of the section to which the relocation applies
@@ -502,18 +527,15 @@ void ELFWriter::EmitRelocations() {
          MRE = Relos.end(); MRI != MRE; ++MRI) {
       MachineRelocation &MR = *MRI;
 
-      // Holds the relocatable field address as an offset from the
-      // beginning of the section where it lives
-      unsigned Offset = MR.getMachineCodeOffset();
+      // Relocatable field offset from the section start
+      unsigned RelOffset = MR.getMachineCodeOffset();
 
       // Symbol index in the symbol table
       unsigned SymIdx = 0;
 
-      // Target specific ELF relocation type
+      // Target specific relocation field type and size
       unsigned RelType = TEW->getRelocationType(MR.getRelocationType());
-
-      // Constant addend used to compute the value to be stored
-      // into the relocatable field
+      unsigned RelTySize = TEW->getRelocationTySize(RelType);
       int64_t Addend = 0;
 
       // There are several machine relocations types, and each one of
@@ -533,29 +555,33 @@ void ELFWriter::EmitRelocations() {
       } else {
         // Get the symbol index for the section symbol
         unsigned SectionIdx = MR.getConstantVal();
+        SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();
+        Addend = (uint64_t)MR.getResultPointer();
+
+        // For pc relative relocations where symbols are defined in the same
+        // section they are referenced, ignore the relocation entry and patch
+        // the relocatable field with the symbol offset directly.
+        if (S.SectionIdx == SectionIdx && TEW->isPCRelativeRel(RelType)) {
+          int64_t Value = TEW->computeRelocation(Addend, RelOffset, RelType);
+          RelocateField(S, RelOffset, Value, RelTySize);
+          continue;
+        }
 
         // Handle Jump Table Index relocation
         if ((SectionIdx == getJumpTableSection().SectionIdx) &&
-            TEW->hasCustomJumpTableIndexRelTy())
+            TEW->hasCustomJumpTableIndexRelTy()) {
           RelType = TEW->getJumpTableIndexRelTy();
-
-        SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();
-        Addend = (uint64_t)MR.getResultPointer();
+          RelTySize = TEW->getRelocationTySize(RelType);
+        }
       }
 
       // 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");
-      }
+      if (!HasRelA)
+        RelocateField(S, RelOffset, Addend, RelTySize);
 
       // Get the relocation entry and emit to the relocation section
-      ELFRelocation Rel(Offset, SymIdx, RelType, HasRelA, Addend);
+      ELFRelocation Rel(RelOffset, SymIdx, RelType, HasRelA, Addend);
       EmitRelocation(RelSec, Rel, HasRelA);
     }
   }
index ec2e44ac2caf17ca7cd880bd40175fad7cb06e25..34f82766c5863eb65b5394575e989f0538e9589a 100644 (file)
@@ -171,18 +171,6 @@ namespace llvm {
                         ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
     }
 
-    /// Return the relocation section of section 'S'. 'RelA' is true
-    /// if the relocation section contains entries with addends.
-    ELFSection &getRelocSection(std::string SName, bool RelA, unsigned Align) {
-      std::string RelSName(".rel");
-      unsigned SHdrTy = RelA ? ELFSection::SHT_RELA : ELFSection::SHT_REL;
-
-      if (RelA) RelSName.append("a");
-      RelSName.append(SName);
-
-      return getSection(RelSName, SHdrTy, 0, Align);
-    }
-
     ELFSection &getNonExecStackSection() {
       return getSection(".note.GNU-stack", ELFSection::SHT_PROGBITS, 0, 1);
     }
@@ -215,6 +203,7 @@ namespace llvm {
 
     ELFSection &getJumpTableSection();
     ELFSection &getConstantPoolSection(MachineConstantPoolEntry &CPE);
+    ELFSection &getRelocSection(ELFSection &S);
 
     // Helpers for obtaining ELF specific info.
     unsigned getGlobalELFBinding(const GlobalValue *GV);
@@ -244,6 +233,8 @@ namespace llvm {
     void EmitSymbolTable();
     void EmitStringTable();
     void OutputSectionsAndSectionTable();
+    void RelocateField(BinaryObject &BO, uint32_t Offset, int64_t Value,
+                       unsigned Size);
     unsigned SortSymbols();
   };
 }
index 9e44f97ca800d38802d780cfcb07f01f1dc65956..618cc5b82b4948310a8c2d37514076a6304c5864 100644 (file)
@@ -103,8 +103,44 @@ unsigned X86ELFWriterInfo::getRelocationTySize(unsigned RelTy) const {
   return 0;
 }
 
+bool X86ELFWriterInfo::isPCRelativeRel(unsigned RelTy) const {
+  if (is64Bit) {
+    switch(RelTy) {
+      case R_X86_64_PC32:
+        return true;
+      case R_X86_64_32:
+      case R_X86_64_32S:
+      case R_X86_64_64:
+        return false;
+    default:
+      llvm_unreachable("unknown x86_64 relocation type");
+    }
+  } else {
+    switch(RelTy) {
+      case R_386_PC32:
+        return true;
+      case R_386_32:
+        return false;
+    default:
+      llvm_unreachable("unknown x86 relocation type");
+    }
+  }
+  return 0;
+}
+
 unsigned X86ELFWriterInfo::getAbsoluteLabelMachineRelTy() const {
   return is64Bit ?
     X86::reloc_absolute_dword : X86::reloc_absolute_word;
 }
 
+long int X86ELFWriterInfo::computeRelocation(unsigned SymOffset,
+                                             unsigned RelOffset,
+                                             unsigned RelTy) const {
+
+  if (RelTy == R_X86_64_PC32 || RelTy == R_386_PC32)
+    return SymOffset - (RelOffset + 4);
+  else
+    assert("computeRelocation unknown for this relocation type");
+
+  return 0;
+}
index e534e17f28ab734562a1cd63be6483659772c00a..e882a0c84b6069519dcfd169e01fb281dd61b437 100644 (file)
@@ -59,16 +59,25 @@ namespace llvm {
     /// for a jump table index.
     virtual unsigned getJumpTableIndexRelTy() const { return R_X86_64_32S; }
 
-    /// getAddendForRelTy - Gets the addend value for an ELF relocation entry
-    /// based on the target relocation type
+    /// getDefaultAddendForRelTy - Gets the default addend value for a
+    /// relocation entry based on the target ELF relocation type.
     virtual long int getDefaultAddendForRelTy(unsigned RelTy) const;
 
     /// getRelTySize - Returns the size of relocatable field in bits
     virtual unsigned getRelocationTySize(unsigned RelTy) const;
 
+    /// isPCRelativeRel - True if the relocation type is pc relative
+    virtual bool isPCRelativeRel(unsigned RelTy) const;
+
     /// getJumpTableRelocationTy - Returns the machine relocation type used
     /// to reference a jumptable.
     virtual unsigned getAbsoluteLabelMachineRelTy() const;
+
+    /// computeRelocation - Some relocatable fields could be relocated
+    /// directly, avoiding the relocation symbol emission, compute the
+    /// final relocation value for this symbol.
+    virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset,
+                                       unsigned RelTy) const;
   };
 
 } // end llvm namespace