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 12f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LinkerConfig.h> 13f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/IRBuilder.h> 146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/Support/MsgHandling.h> 156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/LDSymbol.h> 16f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/Object/ObjectBuilder.h> 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h> 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h> 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 2567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables 2667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_32_APPLY_RELOC_FUNCS 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc, 316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32Relocator& pParent); 3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstruct X86_32ApplyFunctionTriple 3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32ApplyFunctionType func; 3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = { 446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines DECL_X86_32_APPLY_RELOC_FUNC_PTRS 4567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 48d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// X86Relocator 4967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86Relocator::X86Relocator(const LinkerConfig& pConfig) 51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines : Relocator(pConfig) { 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 54d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoX86Relocator::~X86Relocator() 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 58f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86Relocator::scanRelocation(Relocation& pReloc, 59f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pLinker, 60f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 61f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& pSection) 62f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 63f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::Object == config().codeGenType()) 64f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 65f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 66f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 67f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != rsym && 68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines "ResolveInfo of relocation not set while scanRelocation"); 69f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 70f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.updateAddend(); 71f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != pSection.getLink()); 72f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 73f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 74f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 75f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation 76f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // entries should be created. 77f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isLocal()) // rsym is local 78f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines scanLocalReloc(pReloc, pLinker, pModule, pSection); 79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else // rsym is external 80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines scanGlobalReloc(pReloc, pLinker, pModule, pSection); 81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // check if we should issue undefined reference for the relocation target 83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol 84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::undefined_reference) << rsym->name(); 86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86Relocator::addCopyReloc(ResolveInfo& pSym, X86GNULDBackend& pTarget) 89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocation& rel_entry = *pTarget.getRelDyn().consumeEntry(); 91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setType(pTarget.getCopyRelType()); 92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(pSym.outSymbol()->hasFragRef()); 93f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 94f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setSymInfo(&pSym); 95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// defineSymbolforCopyReloc 98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS 99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// section and all other reference to this symbol should refer to this 100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// copy. 101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// @note This is executed at `scan relocation' stage. 102f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesLDSymbol& X86Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const ResolveInfo& pSym, 104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines X86GNULDBackend& pTarget) 105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get or create corresponding BSS LDSection 107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection* bss_sect_hdr = NULL; 108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ELFFileFormat* file_format = pTarget.getOutputFormat(); 109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (ResolveInfo::ThreadLocal == pSym.type()) 110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr = &file_format->getTBSS(); 111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr = &file_format->getBSS(); 113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get or create corresponding BSS SectionData 115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != bss_sect_hdr); 116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines SectionData* bss_section = NULL; 117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (bss_sect_hdr->hasSectionData()) 118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_section = bss_sect_hdr->getSectionData(); 119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr); 121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Determine the alignment by the symbol value 123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: here we use the largest alignment 124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint32_t addralign = config().targets().bitclass() / 8; 125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // allocate space in BSS for the copy symbol 127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t size = ObjectBuilder::AppendFragment(*frag, 129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *bss_section, 130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addralign); 131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 133f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // change symbol binding to Global if it's a weak symbol 134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 135f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (binding == ResolveInfo::Weak) 136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines binding = ResolveInfo::Global; 137f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 138f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Define the copy symbol in the bss section and resolve it 139f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 140f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pSym.name(), 141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (ResolveInfo::Type)pSym.type(), 142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo::Define, 143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines binding, 144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pSym.size(), // size 145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 0x0, // value 146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines FragmentRef::Create(*frag, 0x0), 147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (ResolveInfo::Visibility)pSym.other()); 148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // output all other alias symbols if any 150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module &pModule = pBuilder.getModule(); 151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module::AliasList* alias_list = pModule.getAliasList(pSym); 152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (NULL!=alias_list) { 153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module::alias_iterator it, it_e=alias_list->end(); 154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines for (it=alias_list->begin(); it!=it_e; ++it) { 155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const ResolveInfo* alias = *it; 156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (alias!=&pSym && alias->isDyn()) { 157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines alias->name(), 159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (ResolveInfo::Type)alias->type(), 160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo::Define, 161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines binding, 162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines alias->size(), // size 163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 0x0, // value 164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines FragmentRef::Create(*frag, 0x0), 165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (ResolveInfo::Visibility)alias->other()); 166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return *cpy_sym; 171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32Relocator 1756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent, 177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LinkerConfig& pConfig) 178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines : X86Relocator(pConfig), m_Target(pParent) { 1796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 1806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 181d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result 1826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32Relocator::applyRelocation(Relocation& pRelocation) 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) { 18767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return Unknown; 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 1916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_32ApplyFunctions[type].func(pRelocation, *this); 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst char* X86_32Relocator::getName(Relocation::Type pType) const 19567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 1966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_32ApplyFunctions[pType].name; 1976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 1986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size X86_32Relocator::getSize(Relocation::Type pType) const 2006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 2016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_32ApplyFunctions[pType].size;; 20267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::scanLocalReloc(Relocation& pReloc, 205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& pSection) 208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pReloc.type()){ 213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_32: 215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_16: 216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_8: 217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If buiding PIC object (shared library or PIC executable), 218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Reserve an entry in .rel.dyn 220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeIndep()) { 221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 222f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PLT32: 229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOTOFF: 232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOTPC: 233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: A GOT section is needed 234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOT32: 237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 239f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & (ReserveGOT | GOTRel)) 240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: check STT_GNU_IFUNC symbol 242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(); 243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 244f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If the GOT is used in statically linked binaries, 245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // the GOT entry is enough and no relocation is needed. 246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeStatic()) { 247f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 249f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If building shared object or the symbol is undefined, a dynamic 251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // relocation is needed to relocate this GOT entry. Reserve an 252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // entry in .rel.dyn 253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == 254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOT bit 261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC32: 265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC16: 266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC8: 267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_GD: { 270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: no linker optimization for TLS relocation 271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & GOTRel) 272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(2); 274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // reserve an rel entry 275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // define the section symbol for .tdata or .tbss 279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // the target symbol of the created dynamic relocation should be the 280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // section symbol of the section which this symbol defined. so we 281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // need to define that section symbol here 282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ELFFileFormat* file_format = getTarget().getOutputFormat(); 283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LDSection* sym_sect = 284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection(); 285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (&file_format->getTData() == sym_sect) { 286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!getTarget().hasTDATASymbol()) 287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setTDATASymbol(*pModule.getSectionSymbolSet().get(*sym_sect)); 288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) { 290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!getTarget().hasTBSSSymbol()) 291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setTBSSSymbol(*pModule.getSectionSymbolSet().get(*sym_sect)); 292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines error(diag::invalid_tls) << rsym->name() << sym_sect->name(); 295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 298f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LDM: 299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTLSModuleID(); 300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LDO_32: 303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_IE: 306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if buildint shared object, a RELATIVE dynamic relocation is needed 308f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 310f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } else { 313f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // for local sym, we can convert ie to le if not building shared object 314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines convertTLSIEtoLE(pReloc, pSection); 315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & GOTRel) 318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // reserve got and dyn relocation entries for tp-relative offset 320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(); 321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 322f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 325f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 326f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 327f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_GOTIE: 328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & GOTRel) 330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 331f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // reserve got and dyn relocation entries for tp-relative offset 332f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(); 333f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 334f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 335f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LE: 340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LE_32: 341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if buildint shared object, a dynamic relocation is needed 343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 345f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 346f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 347f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // the target symbol of the dynamic relocation is rsym, so we need to 348f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // emit it into .dynsym 349f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != rsym->outSymbol()); 350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::unsupported_relocation) << (int)pReloc.type() 356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } // end switch 359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::scanGlobalReloc(Relocation& pReloc, 362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& pSection) 365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pReloc.type()) { 370f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_32: 371f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_16: 372f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_8: 373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Absolute relocation type, symbol may needs PLT entry or 374f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // dynamic relocation entry 375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // in .got and .rel.plt. (GOT entry will be reserved simultaneously 381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // when calling X86PLT->reserveEntry()) 382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getPLT().reserveEntry(); 383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOTPLT().reserve(); 384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelPLT().reserveEntry(); 385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) { 391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else { 398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 400f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(pSection); 401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOTOFF: 406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOTPC: { 407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: A GOT section is needed 408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 411f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PLT32: 412f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // A PLT entry is needed when building shared library 413f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 414f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create plt for this symbol 415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ReservePLT) 416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if the symbol's value can be decided at link time, then no need plt 419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) 420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 421f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 422f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if symbol is defined in the ouput file and it's not 423f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // preemptible, no need plt 424f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isDefine() && !rsym->isDyn() && 425f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines !getTarget().isSymbolPreemptible(*rsym)) { 426f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 427f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 428f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 429f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 430f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 431f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // in .got and .rel.plt. (GOT entry will be reserved simultaneously 432f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // when calling X86PLT->reserveEntry()) 433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getPLT().reserveEntry(); 434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOTPLT().reserve(); 435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelPLT().reserveEntry(); 436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 440f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_GOT32: 441f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 442f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 443f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & (ReserveGOT | GOTRel)) 444f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 445f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(); 446f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 447f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If the GOT is used in statically linked binaries, 448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // the GOT entry is enough and no relocation is needed. 449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeStatic()) { 450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If building shared object or the symbol is undefined, a dynamic 454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // relocation is needed to relocate this GOT entry. Reserve an 455f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // entry in .rel.dyn 456f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == 457f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 458f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 461f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 462f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 463f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOT bit 464f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 465f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 466f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 467f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC32: 468f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC16: 469f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_PC8: 470f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 471f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym) && 472f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LinkerConfig::DynObj != config().codeGenType()) { 473f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 474f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 475f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 476f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 477f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // in .got and .rel.plt. (GOT entry will be reserved simultaneously 478f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // when calling X86PLT->reserveEntry()) 479f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getPLT().reserveEntry(); 480f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOTPLT().reserve(); 481f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelPLT().reserveEntry(); 482f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 483f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 484f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 485f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 486f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 487f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) { 488f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 489f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 490f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 491f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 492f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 493f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 494f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else { 495f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 496f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 497f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(pSection); 498f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 499f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 500f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 501f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 502f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_GD: { 503f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // FIXME: no linker optimization for TLS relocation 504f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & GOTRel) 505f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 506f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // reserve two pairs of got entry and dynamic relocation 507f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(2); 508f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(2); 509f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 510f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 511f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 512f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 513f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 514f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 515f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LDM: 516f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTLSModuleID(); 517f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 518f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 519f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LDO_32: 520f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 521f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 522f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_IE: 523f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 524f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if buildint shared object, a RELATIVE dynamic relocation is needed 525f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 526f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 527f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 528f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 529f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } else { 530f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // for global sym, we can convert ie to le if its final value is known 531f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) { 532f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines convertTLSIEtoLE(pReloc, pSection); 533f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 534f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 535f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 536f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & GOTRel) 537f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 538f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // reserve got and dyn relocation entries for tp-relative offset 539f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(); 540f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 541f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 542f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 543f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 544f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 545f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 546f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_GOTIE: 547f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 548f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & GOTRel) 549f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 550f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // reserve got and dyn relocation entries for tp-relative offset 551f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(); 552f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 553f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 554f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 555f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 556f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 557f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 558f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LE: 559f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_386_TLS_LE_32: 560f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().setHasStaticTLS(); 561f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if buildint shared object, a dynamic relocation is needed 562f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 563f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 564f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol()); 565f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 566f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 568f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 569f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: { 571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::unsupported_relocation) << (int)pReloc.type() 572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 575f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } // end switch 576f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 577f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 578f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// Create a GOT entry for the TLS module index 579f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_32GOTEntry& X86_32Relocator::getTLSModuleID() 580f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 581f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines static X86_32GOTEntry* got_entry = NULL; 582f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (NULL != got_entry) 583f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return *got_entry; 584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM 586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(2); 587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines got_entry = getTarget().getGOT().consume(); 588f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().consume()->setValue(0x0); 589f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 590f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 591f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocation* rel_entry = getTarget().getRelDyn().consumeEntry(); 592f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32); 593f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry->targetRef().assign(*got_entry, 0x0); 594f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry->setSymInfo(NULL); 595f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 596f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return *got_entry; 597f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 598f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// convert R_386_TLS_IE to R_386_TLS_LE 600f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::convertTLSIEtoLE(Relocation& pReloc, 601f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& pSection) 602f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 603f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(pReloc.type() == llvm::ELF::R_386_TLS_IE); 604f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != pReloc.targetRef().frag()); 605f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 606f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 1. create the fragment references and new relocs 607f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t off = pReloc.targetRef().offset(); 608f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (off >= 4) 609f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines off -= 4; 610f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 611f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines off = 0; 612f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines FragmentRef* fragref = FragmentRef::Create(*pReloc.targetRef().frag(), off); 614f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // TODO: add symbols for R_386_TLS_OPT relocs 615f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocation* reloc = Relocation::Create(X86_32Relocator::R_386_TLS_OPT, 616f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *fragref, 617f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 0x0); 618f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 619f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 2. modify the opcodes to the appropriate ones 620f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint8_t* op = (reinterpret_cast<uint8_t*>(&reloc->target())); 621f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines off = pReloc.targetRef().offset() - reloc->targetRef().offset() - 1; 622f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (op[off] == 0xa1) { 623f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines op[off] = 0xb8; 624f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } else { 625f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch (op[off - 1]) { 626f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case 0x8b: 627f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert((op[off] & 0xc7) == 0x05); 628f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines op[off - 1] = 0xc7; 629f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines op[off] = 0xc0 | ((op[off] >> 3) & 7); 630f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 631f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case 0x03: 632f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert((op[off] & 0xc7) == 0x05); 633f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines op[off - 1] = 0x81; 634f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines op[off] = 0xc0 | ((op[off] >> 3) & 7); 635f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 636f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 637f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(0); 638f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 639f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 640f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 641f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 642f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 3. insert the new relocs "BEFORE" the original reloc. 643f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pSection.getRelocData()->getRelocationList().insert( 644f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines RelocData::iterator(pReloc), reloc); 645f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 646f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 4. change the type of the original reloc 647f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.setType(llvm::ELF::R_386_TLS_LE); 648f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 65067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 65167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function 65267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 6535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 65422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// helper_DynRel - Get an relocation entry in .rel.dyn 65522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic 65622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoRelocation& helper_DynRel(ResolveInfo* pSym, 65722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Fragment& pFrag, 65822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pOffset, 659d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Type pType, 6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32Relocator& pParent) 66122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 6626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 66322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 66422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setType(pType); 66522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.targetRef().assign(pFrag, pOffset); 66622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym) 66722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(0); 66822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 66922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(pSym); 67022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 67122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return rel_entry; 67222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 67322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 67422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 67522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// helper_use_relative_reloc - Check if symbol can use relocation 67622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// R_386_RELATIVE 6775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool 6785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_use_relative_reloc(const ResolveInfo& pSym, 6796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const X86_32Relocator& pFactory) 6805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 6825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol is dynamic or undefine or preemptible 683affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pSym.isDyn() || 68422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pSym.isUndef() || 68522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pFactory.getTarget().isSymbolPreemptible(pSym)) 6865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 6875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return true; 6885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 6895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 6916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32Relocator& pParent) 6935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 6945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 6955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 6975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 69922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != got_entry) 70022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 70122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 70222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // not found 70322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = ld_backend.getGOT().consume(); 70422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 70522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 70622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // If we first get this GOT entry, we should initialize it. 707f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReserveGOT) { 70822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // No corresponding dynamic relocation, initialize to the symbol value. 709d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(pReloc.symValue()); 71022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 711f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if (rsym->reserved() & X86Relocator::GOTRel) { 71222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Initialize got_entry content and the corresponding dynamic relocation. 71322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (helper_use_relative_reloc(*rsym, pParent)) { 71422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent); 715d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(pReloc.symValue()); 7165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 7175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 71822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent); 719d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(0); 7205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 7215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 72222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 72322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_got); 72422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 72522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 7265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 7306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent) 7315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 73222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return pParent.getTarget().getGOTPLT().addr(); 7335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 7376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& pParent) 7385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 7396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent); 740d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr(); 74122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return got_addr + got_entry.getOffset(); 7425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 7466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc, 7476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32Relocator& pParent) 7485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 7495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 7505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 7516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 7525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 753d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym); 75422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != plt_entry) 75522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *plt_entry; 75622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 75722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // not found 75822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao plt_entry = ld_backend.getPLT().consume(); 75922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymPLTMap().record(*rsym, *plt_entry); 76022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // If we first get this PLT entry, we should initialize it. 761f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 7626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym); 76322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!"); 76422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao gotplt_entry = ld_backend.getGOTPLT().consume(); 76522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 76622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // init the corresponding rel entry in .rel.plt 76722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry(); 76822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT); 76922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.targetRef().assign(*gotplt_entry); 77022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(rsym); 77122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 77222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 77322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_plt); 7745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 7755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 77622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *plt_entry; 77722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 7785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 7816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent) 7825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 78322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return pParent.getTarget().getPLT().addr(); 7845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 7886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT(Relocation& pReloc, X86_32Relocator& pParent) 7895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 790d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 79122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return helper_PLT_ORG(pParent) + plt_entry.getOffset(); 7925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 7965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation // 7975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 7985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_NONE 8006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent) 8015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 802d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 8035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_32: S + A 80622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_16 80722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_8 8086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent) 8095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 8105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 811d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 812d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 81367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 81422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *rsym, 815f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (rsym->reserved() & X86Relocator::ReservePLT), 81622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao true); 817f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines FragmentRef &target_fragref = pReloc.targetRef(); 818f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Fragment *target_frag = target_fragref.frag(); 8195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 820f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& target_sect = target_frag->getParent()->getSection(); 821affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 822affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 82322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 824affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 825d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 826affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 827affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 828affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // A local symbol may need REL Type dynamic relocation 82967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (rsym->isLocal() && has_dyn_rel) { 830f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines X86Relocator::Type pType = pReloc.type(); 831f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (llvm::ELF::R_386_32 == pType) 832f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pType = llvm::ELF::R_386_RELATIVE; 833f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_DynRel(rsym, *target_frag, target_fragref.offset(), pType, pParent); 8345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A; 835d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 8365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 837affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 838affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 839affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 840f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = helper_PLT(pReloc, pParent); 8425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 843affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If we generate a dynamic relocation (except R_386_RELATIVE) 844affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // for a place, we should not perform static relocation on it 845affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // in order to keep the addend store in the place correct. 84667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (has_dyn_rel) { 84722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (llvm::ELF::R_386_32 == pReloc.type() && 84822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_use_relative_reloc(*rsym, pParent)) { 849f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_DynRel(rsym, *target_frag, target_fragref.offset(), 850f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines llvm::ELF::R_386_RELATIVE, pParent); 8515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 853f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_DynRel(rsym, *target_frag, target_fragref.offset(), 854f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.type(), pParent); 855d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 8565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 8615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A; 862d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PC32: S + A - P 86622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC16 86722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC8 8686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent) 8695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 870affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ResolveInfo* rsym = pReloc.symInfo(); 871d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 872d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 873d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord P = pReloc.place(); 874affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 87522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 876affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 877affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 87822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 879affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 880d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 881affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 882affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 883affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 884affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 885f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 886affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_PLT(pReloc, pParent); 887affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 888affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 889affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pParent.getTarget().symbolNeedsDynRel( 89022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *rsym, 891f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (rsym->reserved() & X86Relocator::ReservePLT), 89222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao false)) { 89322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (helper_use_relative_reloc(*rsym, pParent) ) { 89422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), 89522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent); 896affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 897affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 89822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), 89922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), pReloc.type(), pParent); 900d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 901affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 902affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 903affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 904affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 905affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // perform static relocation 906affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 907d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 9085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTOFF: S + A - GOT_ORG 9116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent) 9125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 913d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 914d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 915d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address S = pReloc.symValue(); 9165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A - GOT_ORG; 918d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 9195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTPC: GOT_ORG + A - P 9226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent) 9235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 924d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 925d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 9265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 92722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_ORG + A - pReloc.place(); 928d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 9295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOT32: GOT(S) + A - GOT_ORG 9326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent) 9335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 934affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!(pReloc.symInfo()->reserved() 935f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines & (X86Relocator::ReserveGOT | X86Relocator::GOTRel))) { 936d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::BadReloc; 9375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 938d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent); 939d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 940d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 9415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 9425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_S + A - GOT_ORG; 943d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 9445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PLT32: PLT(S) + A - P 9476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent) 9485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 9495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // PLT_S depends on if there is a PLT entry. 950d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address PLT_S; 951f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT)) 9525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLT_S = helper_PLT(pReloc, pParent); 9535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 9545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLT_S = pReloc.symValue(); 955d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 956d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address P = pReloc.place(); 9575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = PLT_S + A - P; 958d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 9595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 96022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 96122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GD: 9626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent) 96322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 96422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // global-dynamic 96522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 96622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // must reserve two pairs of got and dynamic relocation 967f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!(rsym->reserved() & X86Relocator::GOTRel)) { 968d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::BadReloc; 96922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 97022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 9716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 97222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ELFFileFormat* file_format = pParent.getTarget().getOutputFormat(); 97322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // setup corresponding got and dynamic relocatio entries: 97422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get first got entry, if there is already a got entry for rsym, then apply 97522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // this relocation to the got entry directly. If not, setup the corresponding 97622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // got and dyn relocation entries 9776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym); 97822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 97922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == got_entry1) { 98022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get and init two got entries if not exist 98122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry1 = ld_backend.getGOT().consume(); 98222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry1); 9836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume(); 984d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry1->setValue(0x0); 985d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry2->setValue(0x0); 98622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // setup dyn rel for get_entry1 98722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0, 98822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::R_386_TLS_DTPMOD32, pParent); 98922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->isLocal()) { 99022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // for local symbol, set got_entry2 to symbol value 991d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry2->setValue(pReloc.symValue()); 99222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 99322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // for local tls symbol, add rel entry against the section symbol this 99422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // symbol belong to (.tdata or .tbss) 99522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const LDSection* sym_sect = 99622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection(); 99722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* sect_sym = NULL; 99822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (&file_format->getTData() == sym_sect) 99922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo(); 100022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 100122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo(); 100222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry1.setSymInfo(sect_sym); 100322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 100422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 100522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // for non-local symbol, add a pair of rel entries against this symbol 100622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // for those two got entries 100722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *got_entry2, 0x0, 100822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::R_386_TLS_DTPOFF32, pParent); 100922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 101022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 101122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 101222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform relocation to the first got entry 1013d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 101422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the 101522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // .got.plt section) 1016d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_OFF = 101722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao file_format->getGOT().addr() + 101822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry1->getOffset() - 101922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao file_format->getGOTPLT().addr(); 102022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_OFF + A; 1021d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 102222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 102322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 102422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDM 10256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent) 102622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 102722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: no linker optimization for TLS relocation 1028f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const X86_32GOTEntry& got_entry = pParent.getTLSModuleID(); 102922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 103022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // All GOT offsets are relative to the end of the GOT. 1031d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::SWord GOT_S = got_entry.getOffset() - 103222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao (pParent.getTarget().getGOTPLT().addr() - 103322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getTarget().getGOT().addr()); 1034d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 103522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 103622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1037d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 103822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 103922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 104022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDO_32 10416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent) 104222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 104322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: no linker optimization for TLS relocation 1044d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 1045d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address S = pReloc.symValue(); 104622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = S + A; 1047d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 104822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 104922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 105022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_IE 10516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent) 105222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 105322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1054f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!(rsym->reserved() & X86Relocator::GOTRel)) { 1055d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::BadReloc; 105622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 105722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1058f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReserveRel) { 105922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // when building shared object, set up a RELATIVE dynamic relocation 106022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(), 106122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::R_386_RELATIVE, pParent); 106222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 106322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 106422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set up the got and dynamic relocation entries if not exist 10656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 106622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == got_entry) { 106722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set got entry 10686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 106922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = ld_backend.getGOT().consume(); 107022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 1071d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(0x0); 107222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set relocation entry 107322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 107422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF); 107522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(rsym); 107622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.targetRef().assign(*got_entry); 107722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 107822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 107922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform relocation to the absolute address of got_entry 1080d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_S = 108122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 108222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1083d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 108422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 108522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1086d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 108722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 108822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 108922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GOTIE 10906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent) 109122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 109222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1093f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!(rsym->reserved() & X86Relocator::GOTRel)) { 1094d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::BadReloc; 109522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 109622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 109722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set up the got and dynamic relocation entries if not exist 10986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 109922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == got_entry) { 110022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set got entry 11016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 110222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = ld_backend.getGOT().consume(); 110322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 1104d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(0x0); 110522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set relocation entry 110622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 110722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF); 110822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(rsym); 110922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.targetRef().assign(*got_entry); 111022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 111122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 111222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // All GOT offsets are relative to the end of the GOT. 1113d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::SWord GOT_S = got_entry->getOffset() - 111422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr()); 1115d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 111622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 111722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1118d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 111922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 112022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 112122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_LE 11226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent) 112322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 112422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel) { 112622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, 112722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *pReloc.targetRef().frag(), 112822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), 112922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::R_386_TLS_TPOFF, 113022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent); 1131d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 113222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 113322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 113422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform static relocation 113522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get TLS segment 113622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find( 113722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0); 1138d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 1139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address S = pReloc.symValue(); 114022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = S + A - tls_seg->memsz(); 1141d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 114222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 114322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent) 114522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 1146d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::Unsupport; 114722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 114822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 11506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Relocation Functions and Tables 11516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 11526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_64_APPLY_RELOC_FUNCS 11536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// the prototype of applying function 11556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc, 11566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64Relocator& pParent); 11576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// the table entry of applying functions 11596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstruct X86_64ApplyFunctionTriple 11606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 11616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64ApplyFunctionType func; 11626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int type; 11636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const char* name; 11646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 11656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}; 11666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// declare the table of applying functions 11686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = { 11696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines DECL_X86_64_APPLY_RELOC_FUNC_PTRS 11706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}; 11716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 11736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64Relocator 11746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 1175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent, 1176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LinkerConfig& pConfig) 1177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines : X86Relocator(pConfig), m_Target(pParent) { 11786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 11796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Result 11816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64Relocator::applyRelocation(Relocation& pRelocation) 11826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 11836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation::Type type = pRelocation.type(); 11846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) { 11866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return Unknown; 11876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // apply the relocation 11906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[type].func(pRelocation, *this); 11916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 11926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst char* X86_64Relocator::getName(Relocation::Type pType) const 11946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 11956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[pType].name; 11966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 11976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size X86_64Relocator::getSize(Relocation::Type pType) const 11996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 12006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[pType].size; 12016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 12026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_64Relocator::scanLocalReloc(Relocation& pReloc, 1204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 1205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 1206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& pSection) 1207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 1208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 1209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pReloc.type()){ 1212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_64: 1213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_32: 1214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_16: 1215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_8: 1216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_32S: 1217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If buiding PIC object (shared library or PIC executable), 1218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 1219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Reserve an entry in .rela.dyn 1220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeIndep()) { 1221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 1222f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 1223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 1224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC32: 1229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC16: 1230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC8: 1231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_GOTPCREL: 1234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 1235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 1236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & (ReserveGOT | GOTRel)) 1237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(); 1239f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If the GOT is used in statically linked binaries, 1241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // the GOT entry is enough and no relocation is needed. 1242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeStatic()) { 1243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 1244f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If building shared object or the symbol is undefined, a dynamic 1247f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // relocation is needed to relocate this GOT entry. Reserve an 1248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // entry in .rela.dyn 1249f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == 1250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 1251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 1252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 1253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 1254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOT bit 1257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 1258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 1261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::unsupported_relocation) << (int)pReloc.type() 1262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 1263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 1264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } // end switch 1265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 1266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_64Relocator::scanGlobalReloc(Relocation& pReloc, 1268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 1269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 1270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& pSection) 1271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 1272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 1273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch(pReloc.type()) { 1276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_64: 1277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_32: 1278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_16: 1279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_8: 1280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_32S: 1281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Absolute relocation type, symbol may needs PLT entry or 1282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // dynamic relocation entry 1283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym)) { 1284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 1285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 1286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 1287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 1288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // in .got and .rela.plt. (GOT entry will be reserved simultaneously 1289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // when calling X86PLT->reserveEntry()) 1290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getPLT().reserveEntry(); 1291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOTPLT().reserve(); 1292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelPLT().reserveEntry(); 1293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 1294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 1295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1298f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) { 1299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol needs dynamic relocation entry, reserve an entry in .rela.dyn 1300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 1301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 1302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 1303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 1304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else { 1306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set Rel bit 1307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 1308f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 1309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1310f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1313f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_GOTPCREL: 1314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs GOT entry, reserve entry in .got 1315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create GOT for this symbol 1316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & (ReserveGOT | GOTRel)) 1317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().reserve(); 1319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If the GOT is used in statically linked binaries, 1321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // the GOT entry is enough and no relocation is needed. 1322f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (config().isCodeStatic()) { 1323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 1324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1325f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1326f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If building shared object or the symbol is undefined, a dynamic 1327f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // relocation is needed to relocate this GOT entry. Reserve an 1328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // entry in .rela.dyn 1329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == 1330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 1331f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 1332f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOTRel bit 1333f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 1334f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1335f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set GOT bit 1337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 1338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PLT32: 1341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // A PLT entry is needed when building shared library 1342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // return if we already create plt for this symbol 1344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & ReservePLT) 1345f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1346f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1347f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if the symbol's value can be decided at link time, then no need plt 1348f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolFinalValueIsKnown(*rsym)) 1349f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // if symbol is defined in the ouput file and it's not 1352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // preemptible, no need plt 1353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isDefine() && !rsym->isDyn() && 1354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines !getTarget().isSymbolPreemptible(*rsym)) { 1355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 1359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 1360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // in .got and .rel.plt. (GOT entry will be reserved simultaneously 1361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // when calling X86PLT->reserveEntry()) 1362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getPLT().reserveEntry(); 1363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOTPLT().reserve(); 1364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelPLT().reserveEntry(); 1365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 1366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 1367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC32: 1370f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC16: 1371f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_X86_64_PC8: 1372f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsPLT(*rsym) && 1373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LinkerConfig::DynObj != config().codeGenType()) { 1374f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // create plt for this symbol if it does not have one 1375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 1376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 1377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and the corresponding GOT and dynamic relocation entry 1378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // in .got and .rel.plt. (GOT entry will be reserved simultaneously 1379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // when calling X86PLT->reserveEntry()) 1380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getPLT().reserveEntry(); 1381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOTPLT().reserve(); 1382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelPLT().reserveEntry(); 1383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // set PLT bit 1384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 1385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Only PC relative relocation against dynamic symbol needs a 1389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // dynamic relocation. Only dynamic copy relocation is allowed 1390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // and PC relative relocation will be resolved to the local copy. 1391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // All other dynamic relocations may lead to run-time relocation 1392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // overflow. 1393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().isDynamicSymbol(*rsym) && 1394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false) && 1395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 1396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 1397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget()); 1398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines addCopyReloc(*cpy_sym.resolveInfo(), getTarget()); 1399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1400f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 1401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 1403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::unsupported_relocation) << (int)pReloc.type() 1404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << "mclinker@googlegroups.com"; 1405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 1406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } // end switch 1407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 1408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===--------------------------------------------------------------------===// 1410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// Relocation helper function 1411f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===--------------------------------------------------------------------===// 14126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// helper_DynRel - Get an relocation entry in .rela.dyn 14136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 14146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocation& helper_DynRel(ResolveInfo* pSym, 14156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Fragment& pFrag, 14166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t pOffset, 14176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Type pType, 14186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64Relocator& pParent) 14196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 14206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 14216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 14226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setType(pType); 14236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.targetRef().assign(pFrag, pOffset); 14246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym) 14256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setSymInfo(0); 14266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else 14276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setSymInfo(pSym); 14286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return rel_entry; 14306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 14316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// helper_use_relative_reloc - Check if symbol can use relocation 14346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// R_X86_64_RELATIVE 14356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic bool 14366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hineshelper_use_relative_reloc(const ResolveInfo& pSym, 14376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const X86_64Relocator& pFactory) 14386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 14406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // if symbol is dynamic or undefine or preemptible 14416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (pSym.isDyn() || 14426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pSym.isUndef() || 14436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pFactory.getTarget().isSymbolPreemptible(pSym)) 14446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return false; 14456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return true; 14466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 14476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 14496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 14506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64Relocator& pParent) 14516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 14526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // rsym - The relocation target symbol 14536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 14546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 14556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 14576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (NULL != got_entry) 14586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *got_entry; 14596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // not found 14616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got_entry = ld_backend.getGOT().consume(); 14626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent.getSymGOTMap().record(*rsym, *got_entry); 14636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If we first get this GOT entry, we should initialize it. 1465f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReserveGOT) { 14666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // No corresponding dynamic relocation, initialize to the symbol value. 14676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got_entry->setValue(pReloc.symValue()); 14686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 1469f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else if (rsym->reserved() & X86Relocator::GOTRel) { 14706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Initialize got_entry content and the corresponding dynamic relocation. 14716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (helper_use_relative_reloc(*rsym, pParent)) { 14726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = helper_DynRel(rsym, *got_entry, 0x0, 14736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines llvm::ELF::R_X86_64_RELATIVE, 14746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent); 14756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setAddend(pReloc.symValue()); 14766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 14776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 14786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT, 14796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent); 14806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 14816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got_entry->setValue(0); 14826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 14836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 14846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::reserve_entry_number_mismatch_got); 14856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 14866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *got_entry; 14876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 14886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 14906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent) 14916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 14926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return pParent.getTarget().getGOT().addr(); 14936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 14946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 14956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 14966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT(Relocation& pReloc, X86_64Relocator& pParent) 14976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 14986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent); 14996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return got_entry.getOffset(); 15006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 15016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 15036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc, 15046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64Relocator& pParent) 15056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 15066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // rsym - The relocation target symbol 15076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 15086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 15096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym); 15116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (NULL != plt_entry) 15126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *plt_entry; 15136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // not found 15156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines plt_entry = ld_backend.getPLT().consume(); 15166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent.getSymPLTMap().record(*rsym, *plt_entry); 15176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If we first get this PLT entry, we should initialize it. 1518f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 15196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym); 15206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!"); 15216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines gotplt_entry = ld_backend.getGOTPLT().consume(); 15226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 15236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // init the corresponding rel entry in .rel.plt 15246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry(); 15256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT); 15266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.targetRef().assign(*gotplt_entry); 15276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setSymInfo(rsym); 15286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 15296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 15306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::reserve_entry_number_mismatch_plt); 15316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 15326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *plt_entry; 15346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 15356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 15376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent) 15386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 15396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return pParent.getTarget().getPLT().addr(); 15406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 15416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 15436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT(Relocation& pReloc, X86_64Relocator& pParent) 15446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 15456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 15466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return helper_PLT_ORG(pParent) + plt_entry.getOffset(); 15476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 15486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// 15506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_NONE 15516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent) 15526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 15536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 15546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 15556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_64: S + A 15576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32: 15586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_16: 15596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_8 15606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent) 15616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 15626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1563f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 15646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 15656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 15666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *rsym, 1567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (rsym->reserved() & X86Relocator::ReservePLT), 15686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines true); 15696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines FragmentRef &target_fragref = pReloc.targetRef(); 1571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Fragment *target_frag = target_fragref.frag(); 1572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 1573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& target_sect = target_frag->getParent()->getSection(); 15746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the flag of target section is not ALLOC, we will not scan this relocation 15756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // but perform static relocation. (e.g., applying .debug section) 15766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 15776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 15786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 15796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 15806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1581f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // A local symbol may need RELA Type dynamic relocation 15826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->isLocal() && has_dyn_rel) { 1583f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines X86Relocator::Type pType = pReloc.type(); 1584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (llvm::ELF::R_X86_64_64 == pType) 1585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pType = llvm::ELF::R_X86_64_RELATIVE; 1586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocation& rel_entry = helper_DynRel(rsym, *target_frag, 1587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines target_fragref.offset(), pType, pParent); 1588f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setAddend(S + A); 15896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 15906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 15916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 15926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 15936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!rsym->isLocal()) { 1594f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 15956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines S = helper_PLT(pReloc, pParent); 15966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 1597f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // If we generate a dynamic relocation (except R_X86_64_RELATIVE) 1598f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // for a place, we should not perform static relocation on it 1599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // in order to keep the addend store in the place correct. 1600f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (has_dyn_rel) { 1601f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (llvm::ELF::R_X86_64_64 == pReloc.type() && 1602f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_use_relative_reloc(*rsym, pParent)) { 1603f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocation& rel_entry = helper_DynRel(rsym, *target_frag, 1604f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines target_fragref.offset(), llvm::ELF::R_X86_64_RELATIVE, pParent); 1605f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setAddend(S + A); 1606f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1607f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else { 1608f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocation& rel_entry = helper_DynRel(rsym, *target_frag, 1609f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines target_fragref.offset(), pReloc.type(), pParent); 1610f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setAddend(A); 1611f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return X86Relocator::OK; 1612f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 16146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 16156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // perform static relocation 16176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 16186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 16196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 16206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32S: S + A 16226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent) 16236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 16246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1625f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 16266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 16276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 16286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *rsym, 1629f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (rsym->reserved() & X86Relocator::ReservePLT), 16306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines true); 16316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // There should be no dynamic relocations for R_X86_64_32S. 16336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (has_dyn_rel) 16346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::BadReloc; 1635f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 16366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 16376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the flag of target section is not ALLOC, we will not scan this relocation 16386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // but perform static relocation. (e.g., applying .debug section) 16396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 16406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) && 1641f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines !rsym->isLocal() && rsym->reserved() & X86Relocator::ReservePLT) 16426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines S = helper_PLT(pReloc, pParent); 16436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1644f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#if notyet 16456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Check 32-bit signed overflow. 16466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::SWord V = S + A; 16476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000)) 16486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::Overflow; 1649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#endif 16506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // perform static relocation 16526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 16536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 16546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 16556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P 16576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent) 16586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 16596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!(pReloc.symInfo()->reserved() 1660f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines & (X86Relocator::ReserveGOT | X86Relocator::GOTRel))) { 16616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::BadReloc; 16626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 16636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent); 1664f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 16656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 16666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Apply relocation. 16676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place(); 16686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 16696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 16706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PLT32: PLT(S) + A - P 16726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent) 16736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 16746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // PLT_S depends on if there is a PLT entry. 16756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Address PLT_S; 1676f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT)) 16776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLT_S = helper_PLT(pReloc, pParent); 16786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else 16796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLT_S = pReloc.symValue(); 1680f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 16816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Address P = pReloc.place(); 16826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = PLT_S + A - P; 16836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 16846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 16856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC32: S + A - P 16876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC16 16886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC8 16896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent) 16906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 16916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 1692f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocator::DWord A = pReloc.target() + pReloc.addend(); 16936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 16946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord P = pReloc.place(); 16956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 16966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 16976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the flag of target section is not ALLOC, we will not scan this relocation 16986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // but perform static relocation. (e.g., applying .debug section) 16996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 17006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A - P; 17016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 17026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 17036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 17046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 17056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!rsym->isLocal()) { 1706f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & X86Relocator::ReservePLT) { 17076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines S = helper_PLT(pReloc, pParent); 17086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A - P; 17096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 17106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (pParent.getTarget().symbolNeedsDynRel( 17116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *rsym, 1712f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines (rsym->reserved() & X86Relocator::ReservePLT), 17136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines false)) { 17146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::Overflow; 17156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 17166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 17176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 17186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // perform static relocation 17196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A - P; 17206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 17216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 17226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 17236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent) 17246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 17256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::Unsupport; 17266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 1727