diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/ELFWriter.cpp | 80 | ||||
-rw-r--r-- | lib/CodeGen/ELFWriter.h | 15 | ||||
-rw-r--r-- | lib/Target/X86/X86ELFWriterInfo.cpp | 36 | ||||
-rw-r--r-- | lib/Target/X86/X86ELFWriterInfo.h | 13 |
4 files changed, 103 insertions, 41 deletions
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index 527adb821e..f04efd5c8c 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -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); } } diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h index ec2e44ac2c..34f82766c5 100644 --- a/lib/CodeGen/ELFWriter.h +++ b/lib/CodeGen/ELFWriter.h @@ -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(); }; } diff --git a/lib/Target/X86/X86ELFWriterInfo.cpp b/lib/Target/X86/X86ELFWriterInfo.cpp index 9e44f97ca8..618cc5b82b 100644 --- a/lib/Target/X86/X86ELFWriterInfo.cpp +++ b/lib/Target/X86/X86ELFWriterInfo.cpp @@ -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; +} diff --git a/lib/Target/X86/X86ELFWriterInfo.h b/lib/Target/X86/X86ELFWriterInfo.h index e534e17f28..e882a0c84b 100644 --- a/lib/Target/X86/X86ELFWriterInfo.h +++ b/lib/Target/X86/X86ELFWriterInfo.h @@ -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 |