From 171375f73a733edcd7a5f839491cc8da4fdeddfe Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Sat, 18 Jul 2009 19:30:09 +0000 Subject: [PATCH] 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 --- include/llvm/Target/TargetELFWriterInfo.h | 9 ++++- lib/CodeGen/ELF.h | 7 ++++ lib/CodeGen/ELFCodeEmitter.cpp | 5 ++- lib/CodeGen/ELFWriter.cpp | 40 ++++++++++++++++----- lib/CodeGen/ELFWriter.h | 8 +++-- lib/Target/X86/X86ELFWriterInfo.cpp | 43 ++++++++++++++++++++--- lib/Target/X86/X86ELFWriterInfo.h | 9 ++++- 7 files changed, 103 insertions(+), 18 deletions(-) diff --git a/include/llvm/Target/TargetELFWriterInfo.h b/include/llvm/Target/TargetELFWriterInfo.h index a5b30c4f6e3..dbcffe0ca64 100644 --- a/include/llvm/Target/TargetELFWriterInfo.h +++ b/include/llvm/Target/TargetELFWriterInfo.h @@ -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 diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h index 8bbb29c7bc1..d4dc151494c 100644 --- a/lib/CodeGen/ELF.h +++ b/lib/CodeGen/ELF.h @@ -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) {} diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp index 1d150032c39..6e6ba8ec6ac 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 @@ 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 diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index 3e1645b2c34..69220f9aeaa 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -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::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); diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h index ee5a856ac22..89ab00c397d 100644 --- a/lib/CodeGen/ELFWriter.h +++ b/lib/CodeGen/ELFWriter.h @@ -107,8 +107,8 @@ namespace llvm { std::map 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 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 SymbolList; + /// PrivateSyms - Record private symbols, every symbol here must never be + /// present in the SymbolList. + std::vector 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. diff --git a/lib/Target/X86/X86ELFWriterInfo.cpp b/lib/Target/X86/X86ELFWriterInfo.cpp index 2736a81cdd5..4002e265304 100644 --- a/lib/Target/X86/X86ELFWriterInfo.cpp +++ b/lib/Target/X86/X86ELFWriterInfo.cpp @@ -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; +} + diff --git a/lib/Target/X86/X86ELFWriterInfo.h b/lib/Target/X86/X86ELFWriterInfo.h index 2ba1a0bd70a..f372658f706 100644 --- a/lib/Target/X86/X86ELFWriterInfo.h +++ b/lib/Target/X86/X86ELFWriterInfo.h @@ -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