diff options
author | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2009-07-18 19:30:09 +0000 |
---|---|---|
committer | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2009-07-18 19:30:09 +0000 |
commit | 171375f73a733edcd7a5f839491cc8da4fdeddfe (patch) | |
tree | 4443b1ad020ebce746c558e8da7477ea90337b27 /lib/CodeGen/ELFWriter.cpp | |
parent | 76e7ba893fecd35422719acad5ab19af09bf4139 (diff) |
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
Diffstat (limited to 'lib/CodeGen/ELFWriter.cpp')
-rw-r--r-- | lib/CodeGen/ELFWriter.cpp | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index 3e1645b2c3..69220f9aea 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<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); |