X86Relocator.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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 126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/Support/MsgHandling.h> 136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/LDSymbol.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h> 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h> 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 2267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables 2367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_32_APPLY_RELOC_FUNCS 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc, 286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32Relocator& pParent); 2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstruct X86_32ApplyFunctionTriple 3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32ApplyFunctionType func; 3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = { 416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines DECL_X86_32_APPLY_RELOC_FUNC_PTRS 4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 45d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// X86Relocator 4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::X86Relocator() 486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : Relocator() { 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 51d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoX86Relocator::~X86Relocator() 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32Relocator 576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent) 596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : X86Relocator(), m_Target(pParent) { 606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 62d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result 636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32Relocator::applyRelocation(Relocation& pRelocation) 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) { 6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return Unknown; 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_32ApplyFunctions[type].func(pRelocation, *this); 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst char* X86_32Relocator::getName(Relocation::Type pType) const 7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_32ApplyFunctions[pType].name; 786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size X86_32Relocator::getSize(Relocation::Type pType) const 816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_32ApplyFunctions[pType].size;; 8367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 8667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function 8767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// helper_DynRel - Get an relocation entry in .rel.dyn 9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic 9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoRelocation& helper_DynRel(ResolveInfo* pSym, 9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Fragment& pFrag, 9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pOffset, 94d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Type pType, 956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32Relocator& pParent) 9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setType(pType); 10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.targetRef().assign(pFrag, pOffset); 10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym) 10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(0); 10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(pSym); 10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return rel_entry; 10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// helper_use_relative_reloc - Check if symbol can use relocation 11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// R_386_RELATIVE 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_use_relative_reloc(const ResolveInfo& pSym, 1146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const X86_32Relocator& pFactory) 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol is dynamic or undefine or preemptible 118affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pSym.isDyn() || 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pSym.isUndef() || 12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pFactory.getTarget().isSymbolPreemptible(pSym)) 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return true; 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 1276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32Relocator& pParent) 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != got_entry) 13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // not found 13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = ld_backend.getGOT().consume(); 13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // If we first get this GOT entry, we should initialize it. 14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & X86GNULDBackend::ReserveGOT) { 14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // No corresponding dynamic relocation, initialize to the symbol value. 144d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(pReloc.symValue()); 14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else if (rsym->reserved() & X86GNULDBackend::GOTRel) { 14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Initialize got_entry content and the corresponding dynamic relocation. 14822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (helper_use_relative_reloc(*rsym, pParent)) { 14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent); 150d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(pReloc.symValue()); 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent); 154d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(0); 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_got); 15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent) 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 16722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return pParent.getTarget().getGOTPLT().addr(); 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& pParent) 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent); 175d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr(); 17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return got_addr + got_entry.getOffset(); 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc, 1826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32Relocator& pParent) 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 188d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym); 18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != plt_entry) 19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *plt_entry; 19122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 19222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // not found 19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao plt_entry = ld_backend.getPLT().consume(); 19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymPLTMap().record(*rsym, *plt_entry); 19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // If we first get this PLT entry, we should initialize it. 19622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 1976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym); 19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!"); 19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao gotplt_entry = ld_backend.getGOTPLT().consume(); 20022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 20122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // init the corresponding rel entry in .rel.plt 20222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry(); 20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT); 20422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.targetRef().assign(*gotplt_entry); 20522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(rsym); 20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 20822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_plt); 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 21122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *plt_entry; 21222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent) 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 21822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return pParent.getTarget().getPLT().addr(); 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT(Relocation& pReloc, X86_32Relocator& pParent) 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 225d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 22622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return helper_PLT_ORG(pParent) + plt_entry.getOffset(); 2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation // 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_NONE 2356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent) 2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 237d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_32: S + A 24122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_16 24222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_8 2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent) 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 246d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 247d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 24867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 24922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *rsym, 25022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao (rsym->reserved() & X86GNULDBackend::ReservePLT), 25122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao true); 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 25322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 254affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 255affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 25622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 257affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 258d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 260affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 261affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // A local symbol may need REL Type dynamic relocation 26267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (rsym->isLocal() && has_dyn_rel) { 26322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (llvm::ELF::R_386_32 == pReloc.type()) { 26422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), 26522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, 26622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent); 26722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 26822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 26922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: check Section symbol 27022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), 27122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), pReloc.type(), pParent); 27222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A; 274d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 276affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 277affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 278affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 279affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = helper_PLT(pReloc, pParent); 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 282affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If we generate a dynamic relocation (except R_386_RELATIVE) 283affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // for a place, we should not perform static relocation on it 284affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // in order to keep the addend store in the place correct. 28567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (has_dyn_rel) { 28622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (llvm::ELF::R_386_32 == pReloc.type() && 28722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_use_relative_reloc(*rsym, pParent)) { 28822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), 28922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent); 2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 29222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), 29322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), pReloc.type(), pParent); 294d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A; 301d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PC32: S + A - P 30522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC16 30622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC8 3076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent) 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 309affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ResolveInfo* rsym = pReloc.symInfo(); 310d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 311d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 312d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord P = pReloc.place(); 313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 31422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 31722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 318affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 319d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 322affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 324affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_PLT(pReloc, pParent); 326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pParent.getTarget().symbolNeedsDynRel( 32922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *rsym, 33022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao (rsym->reserved() & X86GNULDBackend::ReservePLT), 33122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao false)) { 33222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (helper_use_relative_reloc(*rsym, pParent) ) { 33322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), 33422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent); 335affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 336affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 33722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), 33822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), pReloc.type(), pParent); 339d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 340affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 341affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 342affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 343affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 344affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // perform static relocation 345affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 346d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTOFF: S + A - GOT_ORG 3506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent) 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 352d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 353d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 354d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address S = pReloc.symValue(); 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A - GOT_ORG; 357d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTPC: GOT_ORG + A - P 3616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent) 3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 363d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 364d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 36622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_ORG + A - pReloc.place(); 367d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOT32: GOT(S) + A - GOT_ORG 3716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent) 3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 373affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!(pReloc.symInfo()->reserved() 3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) { 375d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::BadReloc; 3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 377d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent); 378d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 379d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_S + A - GOT_ORG; 382d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PLT32: PLT(S) + A - P 3866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent) 3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // PLT_S depends on if there is a PLT entry. 389d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address PLT_S; 390affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT)) 3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLT_S = helper_PLT(pReloc, pParent); 3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLT_S = pReloc.symValue(); 394d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 395d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address P = pReloc.place(); 3965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = PLT_S + A - P; 397d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 3985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 39922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 40022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GD: 4016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent) 40222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 40322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // global-dynamic 40422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 40522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // must reserve two pairs of got and dynamic relocation 40622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) { 407d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::BadReloc; 40822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 40922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 4106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 41122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ELFFileFormat* file_format = pParent.getTarget().getOutputFormat(); 41222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // setup corresponding got and dynamic relocatio entries: 41322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get first got entry, if there is already a got entry for rsym, then apply 41422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // this relocation to the got entry directly. If not, setup the corresponding 41522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // got and dyn relocation entries 4166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym); 41722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 41822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == got_entry1) { 41922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get and init two got entries if not exist 42022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry1 = ld_backend.getGOT().consume(); 42122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry1); 4226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume(); 423d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry1->setValue(0x0); 424d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry2->setValue(0x0); 42522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // setup dyn rel for get_entry1 42622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0, 42722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::R_386_TLS_DTPMOD32, pParent); 42822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->isLocal()) { 42922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // for local symbol, set got_entry2 to symbol value 430d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry2->setValue(pReloc.symValue()); 43122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 43222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // for local tls symbol, add rel entry against the section symbol this 43322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // symbol belong to (.tdata or .tbss) 43422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const LDSection* sym_sect = 43522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection(); 43622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* sect_sym = NULL; 43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (&file_format->getTData() == sym_sect) 43822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo(); 43922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 44022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo(); 44122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry1.setSymInfo(sect_sym); 44222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 44322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 44422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // for non-local symbol, add a pair of rel entries against this symbol 44522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // for those two got entries 44622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *got_entry2, 0x0, 44722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::R_386_TLS_DTPOFF32, pParent); 44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 44922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 45022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 45122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform relocation to the first got entry 452d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 45322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the 45422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // .got.plt section) 455d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_OFF = 45622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao file_format->getGOT().addr() + 45722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry1->getOffset() - 45822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao file_format->getGOTPLT().addr(); 45922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_OFF + A; 460d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 46122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 46222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 46322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDM 4646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent) 46522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 46622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: no linker optimization for TLS relocation 4676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const X86_32GOTEntry& got_entry = pParent.getTarget().getTLSModuleID(); 46822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 46922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // All GOT offsets are relative to the end of the GOT. 470d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::SWord GOT_S = got_entry.getOffset() - 47122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao (pParent.getTarget().getGOTPLT().addr() - 47222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getTarget().getGOT().addr()); 473d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 47422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 47522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 476d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 47722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 47822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 47922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDO_32 4806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent) 48122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 48222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: no linker optimization for TLS relocation 483d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 484d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address S = pReloc.symValue(); 48522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = S + A; 486d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 48822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 48922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_IE 4906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent) 49122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 49222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 49322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) { 494d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::BadReloc; 49522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 49622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 49722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & X86GNULDBackend::ReserveRel) { 49822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // when building shared object, set up a RELATIVE dynamic relocation 49922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(), 50022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::R_386_RELATIVE, pParent); 50122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 50222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 50322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set up the got and dynamic relocation entries if not exist 5046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 50522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == got_entry) { 50622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set got entry 5076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 50822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = ld_backend.getGOT().consume(); 50922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 510d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(0x0); 51122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set relocation entry 51222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 51322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF); 51422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(rsym); 51522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.targetRef().assign(*got_entry); 51622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 51722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 51822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform relocation to the absolute address of got_entry 519d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address GOT_S = 52022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 52122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 522d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 52322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 52422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 525d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 52622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 52722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 52822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GOTIE 5296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent) 53022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 53122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 53222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) { 533d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::BadReloc; 53422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 53522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 53622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set up the got and dynamic relocation entries if not exist 5376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 53822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == got_entry) { 53922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set got entry 5406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GNULDBackend& ld_backend = pParent.getTarget(); 54122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = ld_backend.getGOT().consume(); 54222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 543d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(0x0); 54422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set relocation entry 54522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 54622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF); 54722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.setSymInfo(rsym); 54822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rel_entry.targetRef().assign(*got_entry); 54922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 55022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 55122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // All GOT offsets are relative to the end of the GOT. 552d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::SWord GOT_S = got_entry->getOffset() - 55322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr()); 554d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 55522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = GOT_S + A; 55622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 557d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 55822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 55922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 56022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_LE 5616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent) 56222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 56322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 56422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (pReloc.symInfo()->reserved() & X86GNULDBackend::ReserveRel) { 56522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao helper_DynRel(rsym, 56622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *pReloc.targetRef().frag(), 56722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.targetRef().offset(), 56822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::R_386_TLS_TPOFF, 56922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent); 570d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 57122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 57222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 57322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // perform static relocation 57422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get TLS segment 57522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find( 57622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0); 577d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 578d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao X86Relocator::Address S = pReloc.symValue(); 57922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.target() = S + A - tls_seg->memsz(); 580d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::OK; 58122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 58222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent) 58422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 585d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return X86Relocator::Unsupport; 58622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 58722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 5896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Relocation Functions and Tables 5906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 5916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_64_APPLY_RELOC_FUNCS 5926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 5936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// the prototype of applying function 5946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc, 5956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64Relocator& pParent); 5966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 5976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// the table entry of applying functions 5986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstruct X86_64ApplyFunctionTriple 5996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 6006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64ApplyFunctionType func; 6016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int type; 6026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const char* name; 6036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 6046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}; 6056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// declare the table of applying functions 6076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = { 6086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines DECL_X86_64_APPLY_RELOC_FUNC_PTRS 6096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}; 6106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 6126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64Relocator 6136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===// 6146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent) 6156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : X86Relocator(), m_Target(pParent) { 6166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 6176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Result 6196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64Relocator::applyRelocation(Relocation& pRelocation) 6206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 6216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation::Type type = pRelocation.type(); 6226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) { 6246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return Unknown; 6256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 6266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // apply the relocation 6286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[type].func(pRelocation, *this); 6296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 6306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst char* X86_64Relocator::getName(Relocation::Type pType) const 6326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 6336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[pType].name; 6346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 6356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size X86_64Relocator::getSize(Relocation::Type pType) const 6376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 6386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86_64ApplyFunctions[pType].size; 6396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 6406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// helper_DynRel - Get an relocation entry in .rela.dyn 6426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 6436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocation& helper_DynRel(ResolveInfo* pSym, 6446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Fragment& pFrag, 6456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t pOffset, 6466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Type pType, 6476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64Relocator& pParent) 6486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 6496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 6506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 6516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setType(pType); 6526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.targetRef().assign(pFrag, pOffset); 6536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym) 6546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setSymInfo(0); 6556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else 6566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setSymInfo(pSym); 6576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return rel_entry; 6596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// helper_use_relative_reloc - Check if symbol can use relocation 6636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// R_X86_64_RELATIVE 6646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic bool 6656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hineshelper_use_relative_reloc(const ResolveInfo& pSym, 6666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const X86_64Relocator& pFactory) 6676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 6696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // if symbol is dynamic or undefine or preemptible 6706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (pSym.isDyn() || 6716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pSym.isUndef() || 6726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pFactory.getTarget().isSymbolPreemptible(pSym)) 6736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return false; 6746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return true; 6756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 6766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 6786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 6796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64Relocator& pParent) 6806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 6816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // rsym - The relocation target symbol 6826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 6836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 6846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 6866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (NULL != got_entry) 6876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *got_entry; 6886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // not found 6906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got_entry = ld_backend.getGOT().consume(); 6916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent.getSymGOTMap().record(*rsym, *got_entry); 6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If we first get this GOT entry, we should initialize it. 6946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->reserved() & X86GNULDBackend::ReserveGOT) { 6956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // No corresponding dynamic relocation, initialize to the symbol value. 6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got_entry->setValue(pReloc.symValue()); 6976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 6986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else if (rsym->reserved() & X86GNULDBackend::GOTRel) { 6996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Initialize got_entry content and the corresponding dynamic relocation. 7006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (helper_use_relative_reloc(*rsym, pParent)) { 7016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = helper_DynRel(rsym, *got_entry, 0x0, 7026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines llvm::ELF::R_X86_64_RELATIVE, 7036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent); 7046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setAddend(pReloc.symValue()); 7056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 7066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 7076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT, 7086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent); 7096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 7106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got_entry->setValue(0); 7116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 7126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 7136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::reserve_entry_number_mismatch_got); 7146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 7156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *got_entry; 7166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 7176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 7196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent) 7206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 7216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return pParent.getTarget().getGOT().addr(); 7226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 7236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 7256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT(Relocation& pReloc, X86_64Relocator& pParent) 7266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 7276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent); 7286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return got_entry.getOffset(); 7296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 7306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 7326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc, 7336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64Relocator& pParent) 7346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 7356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // rsym - The relocation target symbol 7366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 7376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GNULDBackend& ld_backend = pParent.getTarget(); 7386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym); 7406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (NULL != plt_entry) 7416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *plt_entry; 7426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // not found 7446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines plt_entry = ld_backend.getPLT().consume(); 7456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent.getSymPLTMap().record(*rsym, *plt_entry); 7466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If we first get this PLT entry, we should initialize it. 7476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 7486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym); 7496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!"); 7506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines gotplt_entry = ld_backend.getGOTPLT().consume(); 7516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 7526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // init the corresponding rel entry in .rel.plt 7536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry(); 7546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT); 7556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.targetRef().assign(*gotplt_entry); 7566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setSymInfo(rsym); 7576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 7586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 7596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::reserve_entry_number_mismatch_plt); 7606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 7616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *plt_entry; 7636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 7646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 7666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent) 7676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 7686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return pParent.getTarget().getPLT().addr(); 7696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 7706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic 7726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT(Relocation& pReloc, X86_64Relocator& pParent) 7736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 7746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 7756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return helper_PLT_ORG(pParent) + plt_entry.getOffset(); 7766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 7776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// 7796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_NONE 7806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent) 7816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 7826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 7836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 7846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_64: S + A 7866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32: 7876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_16: 7886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_8 7896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent) 7906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 7916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 7926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord A = pReloc.addend(); 7936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 7946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 7956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *rsym, 7966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines (rsym->reserved() & X86GNULDBackend::ReservePLT), 7976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines true); 7986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 8006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the flag of target section is not ALLOC, we will not scan this relocation 8016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // but perform static relocation. (e.g., applying .debug section) 8026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 8036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 8046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 8056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 8066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation::Type pointerRel = pParent.getTarget().getPointerRel(); 8086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // A local symbol may need REL Type dynamic relocation 8106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->isLocal() && has_dyn_rel) { 8116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (pointerRel == pReloc.type()) { 8126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(), 8136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.targetRef().offset(), 8146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines llvm::ELF::R_X86_64_RELATIVE, 8156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent); 8166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setAddend(S + A); 8176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 8186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 8196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // FIXME: check Section symbol 8206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(), 8216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.targetRef().offset(), 8226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.type(), pParent); 8236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setAddend(S + A); 8246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 8256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 8266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 8276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 8296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!rsym->isLocal()) { 8306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If we generate a dynamic relocation for a place with explicit 8316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // addend, there is no need to perform static relocation on it. 8326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (has_dyn_rel) { 8336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(), 8346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.targetRef().offset(), 8356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines llvm::ELF::R_X86_64_RELATIVE, 8366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pParent); 8376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Copy addend. 8386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setAddend(A); 8396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 8406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 8416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 8426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines S = helper_PLT(pReloc, pParent); 8436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 8446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 8456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // perform static relocation 8476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 8486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 8496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32S: S + A 8526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent) 8536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 8556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord A = pReloc.addend(); 8566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 8576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 8586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *rsym, 8596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines (rsym->reserved() & X86GNULDBackend::ReservePLT), 8606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines true); 8616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // There should be no dynamic relocations for R_X86_64_32S. 8636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (has_dyn_rel) 8646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::BadReloc; 8656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 8676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the flag of target section is not ALLOC, we will not scan this relocation 8686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // but perform static relocation. (e.g., applying .debug section) 8696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 8706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) && 8716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines !rsym->isLocal() && rsym->reserved() & X86GNULDBackend::ReservePLT) 8726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines S = helper_PLT(pReloc, pParent); 8736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Check 32-bit signed overflow. 8756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::SWord V = S + A; 8766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000)) 8776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::Overflow; 8786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // perform static relocation 8806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A; 8816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 8826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P 8856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent) 8866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!(pReloc.symInfo()->reserved() 8886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) { 8896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::BadReloc; 8906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 8916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent); 8926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord A = pReloc.addend(); 8936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent); 8946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Apply relocation. 8956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place(); 8966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 8976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PLT32: PLT(S) + A - P 9006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent) 9016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 9026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // PLT_S depends on if there is a PLT entry. 9036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Address PLT_S; 9046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT)) 9056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLT_S = helper_PLT(pReloc, pParent); 9066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else 9076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLT_S = pReloc.symValue(); 9086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord A = pReloc.addend(); 9096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86Relocator::Address P = pReloc.place(); 9106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = PLT_S + A - P; 9116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 9126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 9136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC32: S + A - P 9156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC16 9166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC8 9176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent) 9186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 9196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 9206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord A = pReloc.addend(); 9216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord S = pReloc.symValue(); 9226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocator::DWord P = pReloc.place(); 9236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 9256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the flag of target section is not ALLOC, we will not scan this relocation 9266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // but perform static relocation. (e.g., applying .debug section) 9276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 9286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A - P; 9296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 9306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 9316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // An external symbol may need PLT and dynamic relocation 9336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!rsym->isLocal()) { 9346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 9356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines S = helper_PLT(pReloc, pParent); 9366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A - P; 9376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 9386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (pParent.getTarget().symbolNeedsDynRel( 9396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *rsym, 9406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines (rsym->reserved() & X86GNULDBackend::ReservePLT), 9416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines false)) { 9426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::Overflow; 9436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 9446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 9456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // perform static relocation 9476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.target() = S + A - P; 9486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::OK; 9496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 9506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent) 9526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 9536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return X86Relocator::Unsupport; 9546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 955