1d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===- X86Relocator.cpp -------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 96f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "X86Relocator.h" 106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "X86RelocationFunctions.h" 116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFSegmentFactory.h" 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFSegment.h" 1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h" 1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h" 1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h" 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h> 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h> 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 2887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_32 Relocation helper function 2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===// 3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_DynRel - Get an relocation entry in .rel.dyn 3137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocation& helper_DynRel_init(ResolveInfo* pSym, 3237b74a387bb3993387029859c2d9d051c41c724eStephen Hines Fragment& pFrag, 3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint64_t pOffset, 3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::Type pType, 3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_32Relocator& pParent) { 3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *ld_backend.getRelDyn().create(); 3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setType(pType); 3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.targetRef().assign(pFrag, pOffset); 4037b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pType == llvm::ELF::R_386_RELATIVE || pSym == NULL) 4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(NULL); 4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(pSym); 4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return rel_entry; 4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_use_relative_reloc - Check if symbol ceuse relocation 4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// R_386_RELATIVE 5037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic bool helper_use_relative_reloc(const ResolveInfo& pSym, 5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines const X86_32Relocator& pFactory) { 5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // if symbol is dynamic or undefine or preemptible 5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pSym.isDyn() || pSym.isUndef() || 5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pFactory.getTarget().isSymbolPreemptible(pSym)) 5587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return false; 5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return true; 5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 5937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic X86_32GOTEntry& helper_GOT_init(Relocation& pReloc, 6037b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool pHasRel, 6137b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_32Relocator& pParent) { 6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // rsym - The relocation target symbol 6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 6537b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pParent.getSymGOTMap().lookUp(*rsym) == NULL); 6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry = ld_backend.getGOT().create(); 6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymGOTMap().record(*rsym, *got_entry); 6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!pHasRel) { 7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // No corresponding dynamic relocation, initialize to the symbol value. 7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(X86Relocator::SymVal); 7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Initialize got_entry content and the corresponding dynamic relocation. 7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (helper_use_relative_reloc(*rsym, pParent)) { 7637b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent); 7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(X86Relocator::SymVal); 7937b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent); 8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(0x0); 8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *got_entry; 8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 8837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent) { 8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pParent.getTarget().getGOTPLT().addr(); 9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 9237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_get_GOT_address(Relocation& pReloc, 9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_32Relocator& pParent) { 9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(got_entry != NULL); 9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 9937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic PLTEntryBase& helper_PLT_init(Relocation& pReloc, 10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_32Relocator& pParent) { 10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // rsym - The relocation target symbol 10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pParent.getSymPLTMap().lookUp(*rsym) == NULL); 10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines PLTEntryBase* plt_entry = ld_backend.getPLT().create(); 10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymPLTMap().record(*rsym, *plt_entry); 10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // initialize plt and the corresponding gotplt and dyn rel entry. 11037b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pParent.getSymGOTPLTMap().lookUp(*rsym) == NULL && 11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines "PLT entry not exist, but GOTPLT entry exist!"); 11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create(); 11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // init the corresponding rel entry in .rel.plt 11687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *ld_backend.getRelPLT().create(); 11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT); 11887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.targetRef().assign(*gotplt_entry); 11987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(rsym); 12087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *plt_entry; 12187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 12287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 12337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_get_PLT_address(ResolveInfo& pSym, 12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_32Relocator& pParent) { 12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym); 12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(plt_entry != NULL); 12787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 12887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 12987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 13087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===// 13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_32 Relocation Functions and Tables 13267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_32_APPLY_RELOC_FUNCS 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 1366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc, 137551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines X86_32Relocator& pParent); 13867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 13967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 14037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstruct X86_32ApplyFunctionTriple { 1416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32ApplyFunctionType func; 14267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 14367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 1446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 14567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 14667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 14767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 1486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = { 14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines DECL_X86_32_APPLY_RELOC_FUNC_PTRS}; 15067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 152d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// X86Relocator 15367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 15437b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86Relocator::X86Relocator(const LinkerConfig& pConfig) : Relocator(pConfig) { 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 15737b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86Relocator::~X86Relocator() { 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86Relocator::scanRelocation(Relocation& pReloc, 161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pLinker, 162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 16387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& pSection, 16437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Input& pInput) { 165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::Object == config().codeGenType()) 166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 16937b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(rsym != NULL && 170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines "ResolveInfo of relocation not set while scanRelocation"); 171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 17237b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pSection.getLink() != NULL); 17337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0) 174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation 177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // entries should be created. 17837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (rsym->isLocal()) // rsym is local 179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines scanLocalReloc(pReloc, pLinker, pModule, pSection); 18037b74a387bb3993387029859c2d9d051c41c724eStephen Hines else // rsym is external 181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines scanGlobalReloc(pReloc, pLinker, pModule, pSection); 182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // check if we should issue undefined reference for the relocation target 184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol 185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines issueUndefRef(pReloc, pSection, pInput); 187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 18937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86Relocator::addCopyReloc(ResolveInfo& pSym, X86GNULDBackend& pTarget) { 19087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *pTarget.getRelDyn().create(); 191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setType(pTarget.getCopyRelType()); 192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(pSym.outSymbol()->hasFragRef()); 193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setSymInfo(&pSym); 195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// defineSymbolforCopyReloc 198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS 199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// section and all other reference to this symbol should refer to this 200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// copy. 201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// @note This is executed at `scan relocation' stage. 202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesLDSymbol& X86Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const ResolveInfo& pSym, 20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86GNULDBackend& pTarget) { 205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get or create corresponding BSS LDSection 206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection* bss_sect_hdr = NULL; 207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ELFFileFormat* file_format = pTarget.getOutputFormat(); 208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (ResolveInfo::ThreadLocal == pSym.type()) 209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr = &file_format->getTBSS(); 210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr = &file_format->getBSS(); 212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get or create corresponding BSS SectionData 21437b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(bss_sect_hdr != NULL); 215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines SectionData* bss_section = NULL; 216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (bss_sect_hdr->hasSectionData()) 217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_section = bss_sect_hdr->getSectionData(); 218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr); 220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Determine the alignment by the symbol value 222f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: here we use the largest alignment 223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint32_t addralign = config().targets().bitclass() / 8; 224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // allocate space in BSS for the copy symbol 226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 22737b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_section, addralign); 228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // change symbol binding to Global if it's a weak symbol 231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (binding == ResolveInfo::Weak) 233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines binding = ResolveInfo::Global; 234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Define the copy symbol in the bss section and resolve it 236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 23737b74a387bb3993387029859c2d9d051c41c724eStephen Hines pSym.name(), 23837b74a387bb3993387029859c2d9d051c41c724eStephen Hines (ResolveInfo::Type)pSym.type(), 23937b74a387bb3993387029859c2d9d051c41c724eStephen Hines ResolveInfo::Define, 24037b74a387bb3993387029859c2d9d051c41c724eStephen Hines binding, 24137b74a387bb3993387029859c2d9d051c41c724eStephen Hines pSym.size(), // size 24237b74a387bb3993387029859c2d9d051c41c724eStephen Hines 0x0, // value 24337b74a387bb3993387029859c2d9d051c41c724eStephen Hines FragmentRef::Create(*frag, 0x0), 24437b74a387bb3993387029859c2d9d051c41c724eStephen Hines (ResolveInfo::Visibility)pSym.other()); 245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // output all other alias symbols if any 24737b74a387bb3993387029859c2d9d051c41c724eStephen Hines Module& pModule = pBuilder.getModule(); 248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module::AliasList* alias_list = pModule.getAliasList(pSym); 24937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (alias_list != NULL) { 25037b74a387bb3993387029859c2d9d051c41c724eStephen Hines Module::alias_iterator it, it_e = alias_list->end(); 25137b74a387bb3993387029859c2d9d051c41c724eStephen Hines for (it = alias_list->begin(); it != it_e; ++it) { 252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const ResolveInfo* alias = *it; 25337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (alias != &pSym && alias->isDyn()) { 254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 25537b74a387bb3993387029859c2d9d051c41c724eStephen Hines alias->name(), 25637b74a387bb3993387029859c2d9d051c41c724eStephen Hines (ResolveInfo::Type)alias->type(), 25737b74a387bb3993387029859c2d9d051c41c724eStephen Hines ResolveInfo::Define, 25837b74a387bb3993387029859c2d9d051c41c724eStephen Hines binding, 25937b74a387bb3993387029859c2d9d051c41c724eStephen Hines alias->size(), // size 26037b74a387bb3993387029859c2d9d051c41c724eStephen Hines 0x0, // value 26137b74a387bb3993387029859c2d9d051c41c724eStephen Hines FragmentRef::Create(*frag, 0x0), 26237b74a387bb3993387029859c2d9d051c41c724eStephen Hines (ResolveInfo::Visibility)alias->other()); 263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return *cpy_sym; 268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 27037b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===// 2716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32Relocator 27237b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===// 273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent, 274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LinkerConfig& pConfig) 27537b74a387bb3993387029859c2d9d051c41c724eStephen Hines : X86Relocator(pConfig), m_Target(pParent) { 2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 27837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result X86_32Relocator::applyRelocation(Relocation& pRelocation) { 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 28137b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (type >= sizeof(X86_32ApplyFunctions) / sizeof(X86_32ApplyFunctions[0])) { 28267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return Unknown; 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_32ApplyFunctions[type].func(pRelocation, *this); 2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 28937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst char* X86_32Relocator::getName(Relocation::Type pType) const { 2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_32ApplyFunctions[pType].name; 2916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 29337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Size X86_32Relocator::getSize(Relocation::Type pType) const { 29437b74a387bb3993387029859c2d9d051c41c724eStephen Hines return X86_32ApplyFunctions[pType].size; 29567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 29737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool X86_32Relocator::mayHaveFunctionPointerAccess( 29837b74a387bb3993387029859c2d9d051c41c724eStephen Hines const Relocation& pReloc) const { 2990dea6bc96bb52346737966839ac68644f7939f58Stephen Hines switch (pReloc.type()) { 3000dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_386_32: 3010dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_386_16: 3020dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_386_8: 3030dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_386_GOTOFF: 3040dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_386_GOT32: { 3050dea6bc96bb52346737966839ac68644f7939f58Stephen Hines return true; 3060dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 30737b74a387bb3993387029859c2d9d051c41c724eStephen Hines default: { return false; } 3080dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 3090dea6bc96bb52346737966839ac68644f7939f58Stephen Hines} 3100dea6bc96bb52346737966839ac68644f7939f58Stephen Hines 311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::scanLocalReloc(Relocation& pReloc, 31287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines IRBuilder& pBuilder, 31387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Module& pModule, 31437b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSection& pSection) { 315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 31837b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_32: 32087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // If buiding PIC object (shared library or PIC executable), 32187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 32287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Reserve an entry in .rel.dyn 32387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (config().isCodeIndep()) { 32487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set Rel bit 32587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 32687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 32787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up the dyn rel directly 32887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(rsym, 32987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 33087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 33187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::ELF::R_386_RELATIVE, 33287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 33387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 33487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return; 33587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_16: 337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_8: 338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If buiding PIC object (shared library or PIC executable), 339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Reserve an entry in .rel.dyn 341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeIndep()) { 34287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up the dyn rel directly 34337b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init(rsym, 34437b74a387bb3993387029859c2d9d051c41c724eStephen Hines *pReloc.targetRef().frag(), 34537b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.targetRef().offset(), 34637b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.type(), 34737b74a387bb3993387029859c2d9d051c41c724eStephen Hines *this); 348f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 349f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PLT32: 355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOTOFF: 358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOTPC: 359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: A GOT section is needed 360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOT32: 363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 36587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 36787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: check STT_GNU_IFUNC symbol 369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 37037b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If building PIC object, a dynamic relocation with 37137b74a387bb3993387029859c2d9d051c41c724eStephen Hines // type RELATIVE is needed to relocate this GOT entry. 37237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (config().isCodeIndep()) 37387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, true, *this); 37437b74a387bb3993387029859c2d9d051c41c724eStephen Hines else 37537b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_GOT_init(pReloc, false, *this); 37687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 37737b74a387bb3993387029859c2d9d051c41c724eStephen Hines // set GOT bit 378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC32: 382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC16: 383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC8: 384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_GD: { 387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: no linker optimization for TLS relocation 38887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 39087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // define the section symbol for .tdata or .tbss 392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // the target symbol of the created dynamic relocation should be the 393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // section symbol of the section which this symbol defined. so we 394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // need to define that section symbol here 395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ELFFileFormat* file_format = getTarget().getOutputFormat(); 396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LDSection* sym_sect = 39737b74a387bb3993387029859c2d9d051c41c724eStephen Hines &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection(); 39887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSymbol* sect_sym = NULL; 399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (&file_format->getTData() == sym_sect) { 40087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!getTarget().hasTDATASymbol()) { 40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines sect_sym = pModule.getSectionSymbolSet().get(*sym_sect); 40287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().setTDATASymbol(*sect_sym); 40387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 40437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) { 40587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!getTarget().hasTBSSSymbol()) { 40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines sect_sym = pModule.getSectionSymbolSet().get(*sym_sect); 40787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().setTBSSSymbol(*sect_sym); 40887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 40937b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines error(diag::invalid_tls) << rsym->name() << sym_sect->name(); 41137b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 41287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 41387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up a pair of got entries and a dyn rel 41487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set GOT bit 41587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 41687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry1 = getTarget().getGOT().create(); 41787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry2 = getTarget().getGOT().create(); 41887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getSymGOTMap().record(*rsym, *got_entry1, *got_entry2); 41987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up value of got entries, the value of got_entry2 should be the 42087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // symbol value, which has to be set during apply relocation 42187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry1->setValue(0x0); 42287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 42387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // setup dyn rel for got_entry1 42437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation& rel_entry1 = helper_DynRel_init( 42537b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry1, 0x0, llvm::ELF::R_386_TLS_DTPMOD32, *this); 42687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // for local tls symbol, add rel entry against the section symbol this 42787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // symbol belong to (.tdata or .tbss) 42887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry1.setSymInfo(sect_sym->resolveInfo()); 429f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 430f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 431f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LDM: 432f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTLSModuleID(); 433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LDO_32: 436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 43887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_386_TLS_IE: { 439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 44087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // if building shared object, a RELATIVE dynamic relocation is needed 442f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 44337b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init(rsym, 44437b74a387bb3993387029859c2d9d051c41c724eStephen Hines *pReloc.targetRef().frag(), 44537b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.targetRef().offset(), 44637b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::ELF::R_386_RELATIVE, 44737b74a387bb3993387029859c2d9d051c41c724eStephen Hines *this); 448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 45037b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // for local sym, we can convert ie to le if not building shared object 452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines convertTLSIEtoLE(pReloc, pSection); 453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 45587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 45687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 457f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 45887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 45987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up the got and the corresponding rel entry 46087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry = getTarget().getGOT().create(); 46187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getSymGOTMap().record(*rsym, *got_entry); 46287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(0x0); 46337b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 46437b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, *this); 46587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set GOT bit 46687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 46787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // add symbol to dyn sym table 468f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 469f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 47087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 471f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 47287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_386_TLS_GOTIE: { 473f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 47487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 475f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 47687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up the got and the corresponding dyn rel 47787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry = getTarget().getGOT().create(); 47887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getSymGOTMap().record(*rsym, *got_entry); 47987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(0x0); 48037b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 48137b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, *this); 48287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set GOT bit 48387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 484f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 485f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 48687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 487f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 488f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LE: 489f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LE_32: 490f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 491f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if buildint shared object, a dynamic relocation is needed 492f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 49387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(rsym, 49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 49587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::ELF::R_386_TLS_TPOFF, 49787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 498f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 499f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 500f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // the target symbol of the dynamic relocation is rsym, so we need to 501f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // emit it into .dynsym 50237b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(rsym->outSymbol() != NULL); 503f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 504f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 505f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 506f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 507f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 50837b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type()) 509f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 510f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 51137b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end switch 512f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 513f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 514f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::scanGlobalReloc(Relocation& pReloc, 51587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines IRBuilder& pBuilder, 51687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Module& pModule, 51737b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSection& pSection) { 518f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 519f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 520f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 52137b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 522f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_32: 523f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_16: 524f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_8: 525f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Absolute relocation type, symbol may needs PLT entry or 526f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // dynamic relocation entry 527f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 528f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 52937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!(rsym->reserved() & ReservePLT)) { 53087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Symbol needs PLT entry, we need a PLT entry 531f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 53287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // in .got and .rel.plt. 53387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_PLT_init(pReloc, *this); 534f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 535f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 536f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 537f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 538f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 53937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (getTarget() 54037b74a387bb3993387029859c2d9d051c41c724eStephen Hines .symbolNeedsDynRel( 54137b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & ReservePLT), true)) { 54287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // symbol needs dynamic relocation entry, set up the dynrel entry 543f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 54437b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSymbol& cpy_sym = 54537b74a387bb3993387029859c2d9d051c41c724eStephen Hines defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 546f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 54737b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 54887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set Rel bit and the dyn rel 549f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 55187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (llvm::ELF::R_386_32 == pReloc.type() && 55237b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_use_relative_reloc(*rsym, *this)) { 55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(rsym, 55487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 55687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::ELF::R_386_RELATIVE, 55787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 55837b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 55987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(rsym, 56087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 56187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 56287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.type(), 56387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 56437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 565f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 566f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 568f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 569f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOTOFF: 570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOTPC: { 571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: A GOT section is needed 572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 575f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PLT32: 576f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // A PLT entry is needed when building shared library 577f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 578f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create plt for this symbol 579f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ReservePLT) 580f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 581f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 582f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if the symbol's value can be decided at link time, then no need plt 583f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) 584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if symbol is defined in the ouput file and it's not 587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // preemptible, no need plt 588f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isDefine() && !rsym->isDyn() && 58987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines !getTarget().isSymbolPreemptible(*rsym)) 590f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 591f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 59287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Symbol needs PLT entry, we need a PLT entry 593f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 59487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // in .got and .rel.plt 59587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_PLT_init(pReloc, *this); 596f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 597f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 598f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 600f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOT32: 601f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 602f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 60387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 604f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 60537b74a387bb3993387029859c2d9d051c41c724eStephen Hines // if the symbol cannot be fully resolved at link time, then we need a 60637b74a387bb3993387029859c2d9d051c41c724eStephen Hines // dynamic relocation 60737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!getTarget().symbolFinalValueIsKnown(*rsym)) 60887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, true, *this); 60987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 61087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, false, *this); 611f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOT bit 612f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 614f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 615f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC32: 616f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC16: 617f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC8: 618f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 619f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym) && 620f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LinkerConfig::DynObj != config().codeGenType()) { 621f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 62237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!(rsym->reserved() & ReservePLT)) { 62387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Symbol needs PLT entry, we need a PLT entry 624f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 62587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // in .got and .rel.plt. 626f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 62787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_PLT_init(pReloc, *this); 628f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 629f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 630f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 631f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 63237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (getTarget() 63337b74a387bb3993387029859c2d9d051c41c724eStephen Hines .symbolNeedsDynRel( 63437b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & ReservePLT), false)) { 63587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // symbol needs dynamic relocation entry, setup an entry in .rel.dyn 636f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 63737b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSymbol& cpy_sym = 63837b74a387bb3993387029859c2d9d051c41c724eStephen Hines defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 639f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 64037b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 64187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set Rel bit and the dyn rel 642f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 64387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 64487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (llvm::ELF::R_386_32 == pReloc.type() && 64537b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_use_relative_reloc(*rsym, *this)) { 64687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(rsym, 64787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 64887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 64987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::ELF::R_386_RELATIVE, 65087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 65137b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 65287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(rsym, 65387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 65487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 65587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.type(), 65687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 65737b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 658f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 659f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 660f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 661f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 662f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_GD: { 663f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: no linker optimization for TLS relocation 66487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 665f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 66687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 66787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up a pair of got entries and a pair of dyn rel 66887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry1 = getTarget().getGOT().create(); 66987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry2 = getTarget().getGOT().create(); 67087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getSymGOTMap().record(*rsym, *got_entry1, *got_entry2); 67187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry1->setValue(0x0); 67287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry2->setValue(0x0); 67387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // setup dyn rel for got entries against rsym 67437b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 67537b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry1, 0x0, llvm::ELF::R_386_TLS_DTPMOD32, *this); 67637b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 67737b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry2, 0x0, llvm::ELF::R_386_TLS_DTPOFF32, *this); 67887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 67987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // add the rsym to dynamic symbol table 680f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 68187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set GOT bit 68287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 683f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 684f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 685f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 686f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LDM: 687f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTLSModuleID(); 688f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 689f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 690f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LDO_32: 691f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 692f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 69387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_386_TLS_IE: { 694f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 695f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if buildint shared object, a RELATIVE dynamic relocation is needed 696f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 69737b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init(rsym, 69837b74a387bb3993387029859c2d9d051c41c724eStephen Hines *pReloc.targetRef().frag(), 69937b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.targetRef().offset(), 70037b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::ELF::R_386_RELATIVE, 70137b74a387bb3993387029859c2d9d051c41c724eStephen Hines *this); 702f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 703f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 704f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } else { 705f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // for global sym, we can convert ie to le if its final value is known 706f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) { 707f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines convertTLSIEtoLE(pReloc, pSection); 708f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 709f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 710f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 71187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 712f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 71387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up the got and the corresponding rel entry 71487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry = getTarget().getGOT().create(); 71587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getSymGOTMap().record(*rsym, *got_entry); 71687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(0x0); 71737b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 71837b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, *this); 71987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set GOT bit 72087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 721f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 72287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 723f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 72487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_386_TLS_GOTIE: { 725f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 72687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 727f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 72887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up the got and the corresponding dyn rel 72987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry = getTarget().getGOT().create(); 73087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getSymGOTMap().record(*rsym, *got_entry); 73187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(0x0); 73237b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 73337b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, *this); 734f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 73587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set GOT bit 73687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 737f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 73887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 739f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 740f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LE: 741f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LE_32: 742f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 743f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if buildint shared object, a dynamic relocation is needed 744f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 74587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_DynRel_init(rsym, 74687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 74787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 74887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::ELF::R_386_TLS_TPOFF, 74987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 750f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 751f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 752f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 753f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 754f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 755f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 756f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: { 75737b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type()) 758f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 759f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 760f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 76137b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end switch 762f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 763f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 764f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// Create a GOT entry for the TLS module index 76537b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86_32GOTEntry& X86_32Relocator::getTLSModuleID() { 766f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines static X86_32GOTEntry* got_entry = NULL; 76737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (got_entry != NULL) 768f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return *got_entry; 769f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 770f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM 77187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry = getTarget().getGOT().create(); 77287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().getGOT().create()->setValue(0x0); 773f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 77437b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 77537b74a387bb3993387029859c2d9d051c41c724eStephen Hines NULL, *got_entry, 0x0, llvm::ELF::R_386_TLS_DTPMOD32, *this); 776f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return *got_entry; 777f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 778f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 779f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// convert R_386_TLS_IE to R_386_TLS_LE 780f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::convertTLSIEtoLE(Relocation& pReloc, 78137b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSection& pSection) { 782f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(pReloc.type() == llvm::ELF::R_386_TLS_IE); 78337b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pReloc.targetRef().frag() != NULL); 784f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 785551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // 1. create the new relocs 786551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocation* reloc = 78737b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::Create(X86_32Relocator::R_386_TLS_OPT, 78837b74a387bb3993387029859c2d9d051c41c724eStephen Hines *FragmentRef::Create(*pReloc.targetRef().frag(), 78937b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.targetRef().offset() - 1), 79037b74a387bb3993387029859c2d9d051c41c724eStephen Hines 0x0); 79187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // FIXME: should we create a special symbol for the tls opt instead? 79287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines reloc->setSymInfo(pReloc.symInfo()); 793f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 794f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 2. modify the opcodes to the appropriate ones 79537b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint8_t* op = (reinterpret_cast<uint8_t*>(&reloc->target())); 796551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines if (op[0] == 0xa1) { 797551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines op[0] = 0xb8; 798f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } else { 799551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines // create the new reloc (move 1 byte forward). 80037b74a387bb3993387029859c2d9d051c41c724eStephen Hines reloc = Relocation::Create( 80137b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_32Relocator::R_386_TLS_OPT, 80237b74a387bb3993387029859c2d9d051c41c724eStephen Hines *FragmentRef::Create(*pReloc.targetRef().frag(), 80337b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.targetRef().offset() - 2), 80437b74a387bb3993387029859c2d9d051c41c724eStephen Hines 0x0); 805551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines reloc->setSymInfo(pReloc.symInfo()); 806551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines op = (reinterpret_cast<uint8_t*>(&reloc->target())); 807551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines switch (op[0]) { 808f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case 0x8b: 809551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert((op[1] & 0xc7) == 0x05); 810551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines op[0] = 0xc7; 811551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines op[1] = 0xc0 | ((op[1] >> 3) & 7); 812f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 813f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case 0x03: 814551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert((op[1] & 0xc7) == 0x05); 815551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines op[0] = 0x81; 816551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines op[1] = 0xc0 | ((op[1] >> 3) & 7); 817f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 818f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 819f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(0); 820f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 821f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 822f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 823f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 824f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 3. insert the new relocs "BEFORE" the original reloc. 825551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines assert(reloc != NULL); 826f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pSection.getRelocData()->getRelocationList().insert( 82737b74a387bb3993387029859c2d9d051c41c724eStephen Hines RelocData::iterator(pReloc), reloc); 828f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 829f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 4. change the type of the original reloc 830f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.setType(llvm::ELF::R_386_TLS_LE); 831f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 832f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 83337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint32_t X86_32Relocator::getDebugStringOffset(Relocation& pReloc) const { 83437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.type() != llvm::ELF::R_386_32) 83537b74a387bb3993387029859c2d9d051c41c724eStephen Hines error(diag::unsupport_reloc_for_debug_string) 83637b74a387bb3993387029859c2d9d051c41c724eStephen Hines << getName(pReloc.type()) << "mclinker@googlegroups.com"; 83737b74a387bb3993387029859c2d9d051c41c724eStephen Hines 83837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.symInfo()->type() == ResolveInfo::Section) 83937b74a387bb3993387029859c2d9d051c41c724eStephen Hines return pReloc.target(); 84037b74a387bb3993387029859c2d9d051c41c724eStephen Hines else 84137b74a387bb3993387029859c2d9d051c41c724eStephen Hines return pReloc.symInfo()->outSymbol()->fragRef()->offset() + 84237b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() + pReloc.addend(); 84337b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 84437b74a387bb3993387029859c2d9d051c41c724eStephen Hines 84537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_32Relocator::applyDebugStringOffset(Relocation& pReloc, 84637b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint32_t pOffset) { 84737b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = pOffset; 84837b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 84937b74a387bb3993387029859c2d9d051c41c724eStephen Hines 85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//================================================// 85187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_32 Each relocation function implementation // 85287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//================================================// 8535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_NONE 85537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result none(Relocation& pReloc, X86_32Relocator& pParent) { 856551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_32: S + A 86022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_16 86122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_8 86237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent) { 8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 864d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 865d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 86667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 86737b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & X86Relocator::ReservePLT), true); 86887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 86987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 87037b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If the flag of target section is not ALLOC, we will not scan this 87137b74a387bb3993387029859c2d9d051c41c724eStephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 87237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) { 873affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 874551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 875affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 876affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 877affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 878affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 879f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 88087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 8815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 882affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If we generate a dynamic relocation (except R_386_RELATIVE) 883affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // for a place, we should not perform static relocation on it 884affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // in order to keep the addend store in the place correct. 88587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (has_dyn_rel) 88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (llvm::ELF::R_386_32 != pReloc.type() || 88787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (!helper_use_relative_reloc(*rsym, pParent))) 888551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 8925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A; 893551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PC32: S + A - P 89722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC16 89822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC8 89937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent) { 900affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ResolveInfo* rsym = pReloc.symInfo(); 901d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 902d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 903d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord P = pReloc.place(); 90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 90537b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & X86Relocator::ReservePLT), true); 906affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 90722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 90837b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If the flag of target section is not ALLOC, we will not scan this 90937b74a387bb3993387029859c2d9d051c41c724eStephen Hines // relocation 910affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 91137b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) { 912affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 913551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 914affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 915affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 916affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 917affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 918f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 91987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 92087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.target() = S + A - P; 921affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 92287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (has_dyn_rel) 92387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!helper_use_relative_reloc(*rsym, pParent)) 924551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 925affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 926affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 92737b74a387bb3993387029859c2d9d051c41c724eStephen Hines // perform static relocation 928affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 929551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTOFF: S + A - GOT_ORG 93337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent) { 93437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 935551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 936551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 9375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A - GOT_ORG; 939551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTPC: GOT_ORG + A - P 94337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent) { 94437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 945551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 9465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 94722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_ORG + A - pReloc.place(); 948551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOT32: GOT(S) + A - GOT_ORG 95237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent) { 95387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!(rsym->reserved() & (X86Relocator::ReserveGOT))) 955551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 95687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 95787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set up got entry value if the got has no dyn rel or 95887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // the dyn rel is RELATIVE 95987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 96037b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(got_entry != NULL); 96187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (got_entry->getValue() == X86Relocator::SymVal) 96287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(pReloc.symValue()); 96387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 96437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::Address GOT_S = helper_get_GOT_address(pReloc, pParent); 96537b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 966551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 9675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 9685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_S + A - GOT_ORG; 969551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PLT32: PLT(S) + A - P 97337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent) { 9745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // PLT_S depends on if there is a PLT entry. 975551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address PLT_S; 976f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT)) 97787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 9785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 9795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLT_S = pReloc.symValue(); 98037b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 981551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 9825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = PLT_S + A - P; 983551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 98522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 98622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GD: 98737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent) { 98822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // global-dynamic 98922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 99022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // must reserve two pairs of got and dynamic relocation 99187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!(rsym->reserved() & X86Relocator::ReserveGOT)) 992551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 99322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 99422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ELFFileFormat* file_format = pParent.getTarget().getOutputFormat(); 99522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // setup corresponding got and dynamic relocatio entries: 99622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get first got entry, if there is already a got entry for rsym, then apply 99722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // this relocation to the got entry directly. If not, setup the corresponding 99822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // got and dyn relocation entries 99987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUpFirstEntry(*rsym); 100022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 100187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set the got_entry2 value to symbol value 100287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->isLocal()) 100337b74a387bb3993387029859c2d9d051c41c724eStephen Hines pParent.getSymGOTMap().lookUpSecondEntry(*rsym)->setValue( 100437b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.symValue()); 100522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 100622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform relocation to the first got entry 1007d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 100822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the 100922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // .got.plt section) 101037b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::Address GOT_OFF = file_format->getGOT().addr() + 101137b74a387bb3993387029859c2d9d051c41c724eStephen Hines got_entry1->getOffset() - 101237b74a387bb3993387029859c2d9d051c41c724eStephen Hines file_format->getGOTPLT().addr(); 101322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_OFF + A; 1014551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 101522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 101622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 101722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDM 101837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent) { 101922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: no linker optimization for TLS relocation 1020f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const X86_32GOTEntry& got_entry = pParent.getTLSModuleID(); 102122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 102222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // All GOT offsets are relative to the end of the GOT. 102337b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86Relocator::SWord GOT_S = 102437b74a387bb3993387029859c2d9d051c41c724eStephen Hines got_entry.getOffset() - (pParent.getTarget().getGOTPLT().addr() - 102537b74a387bb3993387029859c2d9d051c41c724eStephen Hines pParent.getTarget().getGOT().addr()); 1026d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 102722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 102822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1029551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 103022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 103122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 103222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDO_32 103337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent) { 103422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: no linker optimization for TLS relocation 1035d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 1036551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 103722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = S + A; 1038551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 103922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 104022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 104122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_IE 104237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent) { 104322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 104487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!(rsym->reserved() & X86Relocator::ReserveGOT)) { 104537b74a387bb3993387029859c2d9d051c41c724eStephen Hines return Relocator::BadReloc; 104622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 104722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 104822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set up the got and dynamic relocation entries if not exist 10496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 105037b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(got_entry != NULL); 105122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform relocation to the absolute address of got_entry 1052551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_S = 105337b74a387bb3993387029859c2d9d051c41c724eStephen Hines pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 105422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1055d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 105622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 105722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1058551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 105922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 106022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 106122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GOTIE 106237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent) { 106322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 106487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!(rsym->reserved() & X86Relocator::ReserveGOT)) { 106537b74a387bb3993387029859c2d9d051c41c724eStephen Hines return Relocator::BadReloc; 106622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 106722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 106822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set up the got and dynamic relocation entries if not exist 10696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 107037b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(got_entry != NULL); 107122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 107222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // All GOT offsets are relative to the end of the GOT. 107337b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86Relocator::SWord GOT_S = 107437b74a387bb3993387029859c2d9d051c41c724eStephen Hines got_entry->getOffset() - (pParent.getTarget().getGOTPLT().addr() - 107537b74a387bb3993387029859c2d9d051c41c724eStephen Hines pParent.getTarget().getGOT().addr()); 1076d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 107722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 107822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1079551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 108022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 108122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 108222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_LE 108337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent) { 108487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel) 1085551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 108622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 108722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform static relocation 108822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get TLS segment 108987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ELFSegmentFactory::const_iterator tls_seg = 109037b74a387bb3993387029859c2d9d051c41c724eStephen Hines pParent.getTarget().elfSegmentTable().find( 109137b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0); 109287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(tls_seg != pParent.getTarget().elfSegmentTable().end()); 1093d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 1094551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address S = pReloc.symValue(); 109587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.target() = S + A - (*tls_seg)->memsz(); 1096551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 109722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 109822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 109937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result unsupported(Relocation& pReloc, X86_32Relocator& pParent) { 110037b74a387bb3993387029859c2d9d051c41c724eStephen Hines return Relocator::Unsupported; 110122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 110222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 110487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_64 Relocation helper function 110587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===// 110687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_DynRel - Get an relocation entry in .rela.dyn 110737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocation& helper_DynRel_init(ResolveInfo* pSym, 110837b74a387bb3993387029859c2d9d051c41c724eStephen Hines Fragment& pFrag, 110937b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint64_t pOffset, 111037b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::Type pType, 111137b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_64Relocator& pParent) { 111287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 111387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *ld_backend.getRelDyn().create(); 111487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setType(pType); 111587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.targetRef().assign(pFrag, pOffset); 111637b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pType == llvm::ELF::R_X86_64_RELATIVE || pSym == NULL) 111787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(NULL); 111887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 111987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(pSym); 112087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 112187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return rel_entry; 112287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 112387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 112487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_use_relative_reloc - Check if symbol can use relocation 112587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// R_X86_64_RELATIVE 112637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic bool helper_use_relative_reloc(const ResolveInfo& pSym, 112737b74a387bb3993387029859c2d9d051c41c724eStephen Hines const X86_64Relocator& pFactory) { 112887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // if symbol is dynamic or undefine or preemptible 112937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pSym.isDyn() || pSym.isUndef() || 113087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pFactory.getTarget().isSymbolPreemptible(pSym)) 113187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return false; 113287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return true; 113387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 113487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 113537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic X86_64GOTEntry& helper_GOT_init(Relocation& pReloc, 113637b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool pHasRel, 113737b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_64Relocator& pParent) { 113887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // rsym - The relocation target symbol 113987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 114087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 114137b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pParent.getSymGOTMap().lookUp(*rsym) == NULL); 114287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 114387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_64GOTEntry* got_entry = ld_backend.getGOT().create(); 114487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymGOTMap().record(*rsym, *got_entry); 114587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 114687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // If we first get this GOT entry, we should initialize it. 114787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!pHasRel) { 114887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // No corresponding dynamic relocation, initialize to the symbol value. 114987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(X86Relocator::SymVal); 115037b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 115187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Initialize got_entry content and the corresponding dynamic relocation. 115287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (helper_use_relative_reloc(*rsym, pParent)) { 115337b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation& rel_entry = helper_DynRel_init( 115437b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_RELATIVE, pParent); 115537b74a387bb3993387029859c2d9d051c41c724eStephen Hines rel_entry.setAddend(X86Relocator::SymVal); 115637b74a387bb3993387029859c2d9d051c41c724eStephen Hines pParent.getRelRelMap().record(pReloc, rel_entry); 115737b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 115837b74a387bb3993387029859c2d9d051c41c724eStephen Hines helper_DynRel_init( 115937b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT, pParent); 116087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 116187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(0); 116287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 116387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *got_entry; 116487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 116587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 116637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent) { 116787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pParent.getTarget().getGOT().addr(); 116887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 116987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 117037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_get_GOT_address(Relocation& pReloc, 117137b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_64Relocator& pParent) { 117287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 117337b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(got_entry != NULL); 117487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return got_entry->getOffset(); 117587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 117687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 117737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_get_PLT_address(ResolveInfo& pSym, 117837b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_64Relocator& pParent) { 117987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym); 118037b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(plt_entry != NULL); 118187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 118287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 118387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 118437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic PLTEntryBase& helper_PLT_init(Relocation& pReloc, 118537b74a387bb3993387029859c2d9d051c41c724eStephen Hines X86_64Relocator& pParent) { 118687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // rsym - The relocation target symbol 118787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 118887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 118937b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pParent.getSymPLTMap().lookUp(*rsym) == NULL); 119087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 119187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines PLTEntryBase* plt_entry = ld_backend.getPLT().create(); 119287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymPLTMap().record(*rsym, *plt_entry); 119387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 119487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // initialize plt and the corresponding gotplt and dyn rel entry. 119537b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pParent.getSymGOTPLTMap().lookUp(*rsym) == NULL && 119687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines "PLT entry not exist, but DynRel entry exist!"); 119787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_64GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create(); 119887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 119987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 120087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // init the corresponding rel entry in .rel.plt 120187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& rel_entry = *ld_backend.getRelPLT().create(); 120287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT); 120387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.targetRef().assign(*gotplt_entry); 120487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rel_entry.setSymInfo(rsym); 120587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *plt_entry; 120687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 120787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 120837b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===// 120987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_64 Relocation Functions and Tables 121037b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===// 12116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_64_APPLY_RELOC_FUNCS 12126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// the prototype of applying function 12146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc, 1215551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines X86_64Relocator& pParent); 12166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// the table entry of applying functions 121837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstruct X86_64ApplyFunctionTriple { 12196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64ApplyFunctionType func; 12206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int type; 12216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const char* name; 12226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 12236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}; 12246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// declare the table of applying functions 12266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = { 122737b74a387bb3993387029859c2d9d051c41c724eStephen Hines DECL_X86_64_APPLY_RELOC_FUNC_PTRS}; 12286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 12306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64Relocator 12316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 1232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent, 1233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LinkerConfig& pConfig) 123437b74a387bb3993387029859c2d9d051c41c724eStephen Hines : X86Relocator(pConfig), m_Target(pParent) { 12356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 12366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 123737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result X86_64Relocator::applyRelocation(Relocation& pRelocation) { 12386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation::Type type = pRelocation.type(); 12396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 124037b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (type >= sizeof(X86_64ApplyFunctions) / sizeof(X86_64ApplyFunctions[0])) { 12416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return Unknown; 12426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 12436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // apply the relocation 12456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[type].func(pRelocation, *this); 12466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 12476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 124837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst char* X86_64Relocator::getName(Relocation::Type pType) const { 12496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[pType].name; 12506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 12516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 125237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Size X86_64Relocator::getSize(Relocation::Type pType) const { 12536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[pType].size; 12546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 12556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 125637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool X86_64Relocator::mayHaveFunctionPointerAccess( 125737b74a387bb3993387029859c2d9d051c41c724eStephen Hines const Relocation& pReloc) const { 12580dea6bc96bb52346737966839ac68644f7939f58Stephen Hines bool possible_funcptr_reloc = false; 12590dea6bc96bb52346737966839ac68644f7939f58Stephen Hines switch (pReloc.type()) { 12600dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_64: 12610dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_32: 12620dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_32S: 12630dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_16: 12640dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_8: 12650dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_GOT64: 12660dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_GOT32: 12670dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_GOTPCREL64: 12680dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_GOTPCREL: 12690dea6bc96bb52346737966839ac68644f7939f58Stephen Hines case llvm::ELF::R_X86_64_GOTPLT64: { 12700dea6bc96bb52346737966839ac68644f7939f58Stephen Hines possible_funcptr_reloc = true; 12710dea6bc96bb52346737966839ac68644f7939f58Stephen Hines break; 12720dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 12730dea6bc96bb52346737966839ac68644f7939f58Stephen Hines default: { 12740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines possible_funcptr_reloc = false; 12750dea6bc96bb52346737966839ac68644f7939f58Stephen Hines break; 12760dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 12770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 12780dea6bc96bb52346737966839ac68644f7939f58Stephen Hines 127937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.symInfo()->isGlobal()) { 12800dea6bc96bb52346737966839ac68644f7939f58Stephen Hines return (config().codeGenType() == LinkerConfig::DynObj) && 12810dea6bc96bb52346737966839ac68644f7939f58Stephen Hines ((pReloc.symInfo()->visibility() != ResolveInfo::Default) || 12820dea6bc96bb52346737966839ac68644f7939f58Stephen Hines possible_funcptr_reloc); 128337b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 12840dea6bc96bb52346737966839ac68644f7939f58Stephen Hines return (config().codeGenType() == LinkerConfig::DynObj) || 12850dea6bc96bb52346737966839ac68644f7939f58Stephen Hines possible_funcptr_reloc; 128637b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 12870dea6bc96bb52346737966839ac68644f7939f58Stephen Hines} 12880dea6bc96bb52346737966839ac68644f7939f58Stephen Hines 1289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_64Relocator::scanLocalReloc(Relocation& pReloc, 1290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 1291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 129237b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSection& pSection) { 1293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 1294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 129637b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 1297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_64: 129887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // If buiding PIC object (shared library or PIC executable), 129987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 130087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Reserve an entry in .rela.dyn 130187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (config().isCodeIndep()) { 130287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& reloc = helper_DynRel_init(rsym, 130387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 130487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 130587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::ELF::R_X86_64_RELATIVE, 130687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 130787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getRelRelMap().record(pReloc, reloc); 130887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set Rel bit 130987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 131087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 131187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 131287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return; 131387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_32: 1315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_16: 1316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_8: 1317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_32S: 1318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If buiding PIC object (shared library or PIC executable), 1319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 1320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Reserve an entry in .rela.dyn 1321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeIndep()) { 132287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& reloc = helper_DynRel_init(rsym, 132387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 132487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 132587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.type(), 132687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 132787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getRelRelMap().record(pReloc, reloc); 1328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 1329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 1330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1331f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1332f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1333f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1334f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC32: 1335f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC16: 1336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC8: 1337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_GOTPCREL: 1340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 1341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 134287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 1343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 134537b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If building PIC object, a dynamic relocation with 134637b74a387bb3993387029859c2d9d051c41c724eStephen Hines // type RELATIVE is needed to relocate this GOT entry. 134737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (config().isCodeIndep()) 134887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, true, *this); 134987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 135087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, false, *this); 1351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 1352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 135537b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type()) 1356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 1357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 135837b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end switch 1359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 1360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_64Relocator::scanGlobalReloc(Relocation& pReloc, 1362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 1363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 136437b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSection& pSection) { 1365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 1366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 136837b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 1369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_64: 1370f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_32: 1371f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_16: 1372f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_8: 1373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_32S: 1374f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Absolute relocation type, symbol may needs PLT entry or 1375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // dynamic relocation entry 1376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 1377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 137837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!(rsym->reserved() & ReservePLT)) { 1379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 1380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 138187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // in .got and .rela.plt. 138287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_PLT_init(pReloc, *this); 1383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 1384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 1385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 138837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (getTarget() 138937b74a387bb3993387029859c2d9d051c41c724eStephen Hines .symbolNeedsDynRel( 139037b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & ReservePLT), true)) { 139187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // symbol needs dynamic relocation entry, set up the dynrel entry 1392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 139337b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSymbol& cpy_sym = 139437b74a387bb3993387029859c2d9d051c41c724eStephen Hines defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 1395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 139637b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 139787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set Rel bit and the dyn rel 1398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 139987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 140087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (llvm::ELF::R_386_32 == pReloc.type() && 140187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_use_relative_reloc(*rsym, *this)) { 140287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& reloc = helper_DynRel_init(rsym, 140387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 140487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 140587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::ELF::R_X86_64_RELATIVE, 140687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 140787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getRelRelMap().record(pReloc, reloc); 140837b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 140987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& reloc = helper_DynRel_init(rsym, 141087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *pReloc.targetRef().frag(), 141187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.targetRef().offset(), 141287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.type(), 141387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *this); 141487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getRelRelMap().record(pReloc, reloc); 141587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 1416551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1421f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_GOTPCREL: 1422f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 1423f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 142487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & ReserveGOT) 1425f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1426f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 142737b74a387bb3993387029859c2d9d051c41c724eStephen Hines // if the symbol cannot be fully resolved at link time, then we need a 142837b74a387bb3993387029859c2d9d051c41c724eStephen Hines // dynamic relocation 142937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!getTarget().symbolFinalValueIsKnown(*rsym)) 143087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, true, *this); 143187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 143287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_GOT_init(pReloc, false, *this); 1433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOT bit 1434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 1435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PLT32: 1438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // A PLT entry is needed when building shared library 1439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1440f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create plt for this symbol 1441f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ReservePLT) 1442f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1443f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1444f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if the symbol's value can be decided at link time, then no need plt 1445f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) 1446f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1447f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if symbol is defined in the ouput file and it's not 1449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // preemptible, no need plt 1450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isDefine() && !rsym->isDyn() && 145137b74a387bb3993387029859c2d9d051c41c724eStephen Hines !getTarget().isSymbolPreemptible(*rsym)) { 1452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 145587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Symbol needs PLT entry, we need a PLT entry 1456f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 145787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // in .got and .rel.plt. 145887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_PLT_init(pReloc, *this); 1459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 1460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 1461f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1462f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1463f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC32: 1464f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC16: 1465f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC8: 1466f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym) && 1467f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LinkerConfig::DynObj != config().codeGenType()) { 1468f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 146937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (!(rsym->reserved() & ReservePLT)) { 147087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Symbol needs PLT entry, we need a PLT entry 1471f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 147287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // in .got and .rel.plt. 147387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines helper_PLT_init(pReloc, *this); 1474f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 1475f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 1476f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1477f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1478f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1479f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Only PC relative relocation against dynamic symbol needs a 1480f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // dynamic relocation. Only dynamic copy relocation is allowed 1481f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and PC relative relocation will be resolved to the local copy. 1482f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // All other dynamic relocations may lead to run-time relocation 1483f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // overflow. 1484f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().isDynamicSymbol(*rsym) && 148537b74a387bb3993387029859c2d9d051c41c724eStephen Hines getTarget() 148637b74a387bb3993387029859c2d9d051c41c724eStephen Hines .symbolNeedsDynRel( 148737b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & ReservePLT), false) && 148837b74a387bb3993387029859c2d9d051c41c724eStephen Hines getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 148937b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSymbol& cpy_sym = 149037b74a387bb3993387029859c2d9d051c41c724eStephen Hines defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 1491551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 1492f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1493f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1494f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1495f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 149637b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type()) 1497f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 1498f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 149937b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end switch 1500f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 1501f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 150237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint32_t X86_64Relocator::getDebugStringOffset(Relocation& pReloc) const { 150337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.type() != llvm::ELF::R_X86_64_32) 150437b74a387bb3993387029859c2d9d051c41c724eStephen Hines error(diag::unsupport_reloc_for_debug_string) 150537b74a387bb3993387029859c2d9d051c41c724eStephen Hines << getName(pReloc.type()) << "mclinker@googlegroups.com"; 150637b74a387bb3993387029859c2d9d051c41c724eStephen Hines 150737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.symInfo()->type() == ResolveInfo::Section) 150837b74a387bb3993387029859c2d9d051c41c724eStephen Hines return pReloc.target(); 150937b74a387bb3993387029859c2d9d051c41c724eStephen Hines else 151037b74a387bb3993387029859c2d9d051c41c724eStephen Hines return pReloc.symInfo()->outSymbol()->fragRef()->offset() + 151137b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() + pReloc.addend(); 151237b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 151337b74a387bb3993387029859c2d9d051c41c724eStephen Hines 151437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_64Relocator::applyDebugStringOffset(Relocation& pReloc, 151537b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint32_t pOffset) { 151637b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = pOffset; 151737b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 151837b74a387bb3993387029859c2d9d051c41c724eStephen Hines 151937b74a387bb3993387029859c2d9d051c41c724eStephen Hines//------------------------------------------------// 152037b74a387bb3993387029859c2d9d051c41c724eStephen Hines// X86_64 Each relocation function implementation // 152137b74a387bb3993387029859c2d9d051c41c724eStephen Hines//------------------------------------------------// 15226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_NONE 152337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result none(Relocation& pReloc, X86_64Relocator& pParent) { 1524551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 15256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 15266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_64: S + A 15286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32: 15296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_16: 15306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_8 153137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent) { 15326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1533f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 15346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 153587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 153637b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool has_dyn_rel = (dyn_rel != NULL); 1537f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 153887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 153937b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If the flag of target section is not ALLOC, we will not scan this 154037b74a387bb3993387029859c2d9d051c41c724eStephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 154137b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) { 15426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 1543551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 15446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 15456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1546f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // A local symbol may need RELA Type dynamic relocation 15476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->isLocal() && has_dyn_rel) { 154887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines dyn_rel->setAddend(S + A); 1549551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 15506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 15516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 15536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!rsym->isLocal()) { 1554f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 155587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 15566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 1557f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If we generate a dynamic relocation (except R_X86_64_RELATIVE) 1558f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // for a place, we should not perform static relocation on it 1559f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // in order to keep the addend store in the place correct. 1560f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (has_dyn_rel) { 1561f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (llvm::ELF::R_X86_64_64 == pReloc.type() && 1562f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_use_relative_reloc(*rsym, pParent)) { 156387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines dyn_rel->setAddend(S + A); 156437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 156587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines dyn_rel->setAddend(A); 1566551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 1567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1568f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 15696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 15706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // perform static relocation 15726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 1573551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 15746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 15756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32S: S + A 157737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent) { 15786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1579f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 15806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 15816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // There should be no dynamic relocations for R_X86_64_32S. 158337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pParent.getRelRelMap().lookUp(pReloc) != NULL) 1584551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 1585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 15866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 158737b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If the flag of target section is not ALLOC, we will not scan this 158837b74a387bb3993387029859c2d9d051c41c724eStephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 15896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 159037b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) != 0x0 && !rsym->isLocal() && 159137b74a387bb3993387029859c2d9d051c41c724eStephen Hines rsym->reserved() & X86Relocator::ReservePLT) 159287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines S = helper_get_PLT_address(*rsym, pParent); 15936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1594f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#if notyet 15956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Check 32-bit signed overflow. 15966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::SWord V = S + A; 15976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000)) 1598551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 1599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#endif 16006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // perform static relocation 16026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 1603551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 16046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 16056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P 160737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent) { 160887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!(pReloc.symInfo()->reserved() & X86Relocator::ReserveGOT)) { 1609551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::BadReloc; 16106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 161187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 161287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // set symbol value of the got entry if needed 161387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 161487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (X86Relocator::SymVal == got_entry->getValue()) 161587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry->setValue(pReloc.symValue()); 161687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 161787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // setup relocation addend if needed 161887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 161937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((dyn_rel != NULL) && (X86Relocator::SymVal == dyn_rel->addend())) { 162087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines dyn_rel->setAddend(pReloc.symValue()); 162187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 162287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 162337b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::Address GOT_S = helper_get_GOT_address(pReloc, pParent); 162437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 1625551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 16266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Apply relocation. 16276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place(); 1628551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 16296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 16306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PLT32: PLT(S) + A - P 163237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent) { 16336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // PLT_S depends on if there is a PLT entry. 1634551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address PLT_S; 1635f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT)) 163687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 16376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else 16386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLT_S = pReloc.symValue(); 163937b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 1640551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines Relocator::Address P = pReloc.place(); 16416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = PLT_S + A - P; 1642551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 16436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 16446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC32: S + A - P 16466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC16 16476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC8 164837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent) { 16496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1650f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 16516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 16526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord P = pReloc.place(); 16536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 165537b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If the flag of target section is not ALLOC, we will not scan this 165637b74a387bb3993387029859c2d9d051c41c724eStephen Hines // relocation but perform static relocation. (e.g., applying .debug section) 165737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) { 16586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A - P; 1659551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 16606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 16616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 166287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // setup relocation addend if needed 166387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 166437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((dyn_rel != NULL) && (X86Relocator::SymVal == dyn_rel->addend())) { 166587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines dyn_rel->setAddend(S); 166687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 166787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 16686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 16696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!rsym->isLocal()) { 1670f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 167137b74a387bb3993387029859c2d9d051c41c724eStephen Hines S = helper_get_PLT_address(*rsym, pParent); 16726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 167337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pParent.getTarget() 167437b74a387bb3993387029859c2d9d051c41c724eStephen Hines .symbolNeedsDynRel( 167537b74a387bb3993387029859c2d9d051c41c724eStephen Hines *rsym, (rsym->reserved() & X86Relocator::ReservePLT), false)) { 1676551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::Overflow; 16776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 16786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 16796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 168037b74a387bb3993387029859c2d9d051c41c724eStephen Hines // perform static relocation 16816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A - P; 1682551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 16836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 16846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 168537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result unsupported(Relocation& pReloc, X86_64Relocator& pParent) { 168637b74a387bb3993387029859c2d9d051c41c724eStephen Hines return Relocator::Unsupported; 16876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 168837b74a387bb3993387029859c2d9d051c41c724eStephen Hines 168937b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 1690