15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- X86RelocationFactory.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//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h> 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h> 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/MC/MCLDInfo.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Layout.h> 15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86RelocationFactory.h" 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86RelocationFunctions.h" 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 2367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables 2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_X86_APPLY_RELOC_FUNCS 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaotypedef RelocationFactory::Result 2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao (*ApplyFunctionType)(Relocation& pReloc, 3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const MCLDInfo& pLDInfo, 3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao X86RelocationFactory& pParent); 3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple 3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ApplyFunctionType func; 3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = { 4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao DECL_X86_APPLY_RELOC_FUNC_PTRS 4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===// 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// X86RelocationFactory 4867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::X86RelocationFactory(size_t pNum, 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86GNULDBackend& pParent) 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : RelocationFactory(pNum), 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Target(pParent) { 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::~X86RelocationFactory() 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoRelocationFactory::Result 6067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoX86RelocationFactory::applyRelocation(Relocation& pRelocation, 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo) 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (type >= sizeof (ApplyFunctions) / sizeof (ApplyFunctions[0]) ) { 66affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::unknown_relocation) << (int)type << 67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pRelocation.symInfo()->name(); 6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return Unknown; 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 7267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[type].func(pRelocation, pLDInfo, *this); 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* X86RelocationFactory::getName(Relocation::Type pType) const 7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 7767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[pType].name; 7867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 8167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function 8267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===// 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check if symbol can use relocation R_386_RELATIVE 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_use_relative_reloc(const ResolveInfo& pSym, 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const X86RelocationFactory& pFactory) 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol is dynamic or undefine or preemptible 92affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pSym.isDyn() || 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pSym.isUndef() || 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output())) 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return true; 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoGOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86GNULDBackend& ld_backend = pParent.getTarget(); 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist); 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!exist) { 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this GOT entry, we should initialize it. 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & X86GNULDBackend::ReserveGOT) { 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // No corresponding dynamic relocation, initialize to the symbol value. 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(pReloc.symValue()); 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else if (rsym->reserved() & X86GNULDBackend::GOTRel) { 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Initialize corresponding dynamic relocation. 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelDyn().getEntry(*rsym, true, exist); 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(!exist && "GOT entry not exist, but DynRel entry exist!"); 121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) { 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Initialize got entry to target symbol address 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(pReloc.symValue()); 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_RELATIVE); 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(0); 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(0); 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_GLOB_DAT); 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(rsym); 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef().assign(got_entry); 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 135cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_got); 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return got_entry; 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Address helper_GOT_ORG(X86RelocationFactory& pParent) 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 145affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return pParent.getTarget().getGOTPLT().getSection().addr(); 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Address helper_GOT(Relocation& pReloc, 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo, pParent); 155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang X86RelocationFactory::Address got_addr = 156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pParent.getTarget().getGOT().getSection().addr(); 157affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return got_addr + pParent.getLayout().getOutputOffset(got_entry); 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoPLTEntry& helper_get_PLT_and_init(Relocation& pReloc, 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86GNULDBackend& ld_backend = pParent.getTarget(); 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist); 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (!exist) { 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this PLT entry, we should initialize it. 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& gotplt_entry = 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist); 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Initialize corresponding dynamic relocation. 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelPLT().getEntry(*rsym, true, exist); 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(!exist && "PLT entry not exist, but DynRel entry exist!"); 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT); 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef().assign(gotplt_entry); 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(rsym); 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 185cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_plt); 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return plt_entry; 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Address helper_PLT_ORG(X86RelocationFactory& pParent) 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pParent.getTarget().getPLT().getSection().addr(); 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Address helper_PLT(Relocation& pReloc, 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry); 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Get an relocation entry in .rel.dyn and set its type to pType, 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo() 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory::Type pType, 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86GNULDBackend& ld_backend = pParent.getTarget(); 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelDyn().getEntry(*rsym, false, exist); 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(pType); 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pType == llvm::ELF::R_386_RELATIVE) 2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(0); 2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(rsym); 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation // 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_NONE 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result none(Relocation& pReloc, 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_32: S + A 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result abs32(Relocation& pReloc, 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord S = pReloc.symValue(); 25267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( 25367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), 25467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao pLDInfo, pLDInfo.output(), true); 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 256affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 257affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(pReloc.targetRef().frag())); 258affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != target_sect); 259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 260affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 261affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 262affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 263affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return X86RelocationFactory::OK; 264affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 265affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 266affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // A local symbol may need REL Type dynamic relocation 26767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (rsym->isLocal() && has_dyn_rel) { 2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); 2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A; 2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 272affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 273affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 274affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 275affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao S = helper_PLT(pReloc, pParent); 2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A; 2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 279affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If we generate a dynamic relocation (except R_386_RELATIVE) 280affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // for a place, we should not perform static relocation on it 281affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // in order to keep the addend store in the place correct. 28267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (has_dyn_rel) { 283affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) { 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); 2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, pReloc.type(), pParent); 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // perform static relocation 2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A; 2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PC32: S + A - P 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result rel32(Relocation& pReloc, 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 303affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ResolveInfo* rsym = pReloc.symInfo(); 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 305affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord S = pReloc.symValue(); 306affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 307affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 308affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 309affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(pReloc.targetRef().frag())); 310affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != target_sect); 311affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 312affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 314affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return X86RelocationFactory::OK; 316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 317affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 318affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // An external symbol may need PLT and dynamic relocation 319affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!rsym->isLocal()) { 320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & X86GNULDBackend::ReservePLT) { 321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang S = helper_PLT(pReloc, pParent); 322affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 324affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pParent.getTarget().symbolNeedsDynRel( 325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo, 326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pLDInfo.output(), false)) { 327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) { 328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); 329affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 330affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 331affc150dc44fab1911775a49636d0ce85333b634Zonr Chang helper_DynRel(pReloc, pReloc.type(), pParent); 332affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return X86RelocationFactory::OK; 333affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 334affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 335affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 336affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 337affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // perform static relocation 338affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A - P; 3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTOFF: S + A - GOT_ORG 3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result gotoff32(Relocation& pReloc, 3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory::Address S = pReloc.symValue(); 3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = S + A - GOT_ORG; 3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTPC: GOT_ORG + A - P 3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result gotpc32(Relocation& pReloc, 3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); 3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_ORG + A - pReloc.place(pParent.getLayout()); 3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOT32: GOT(S) + A - GOT_ORG 3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result got32(Relocation& pReloc, 3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 372affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!(pReloc.symInfo()->reserved() 3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) { 3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::BadReloc; 3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent); 3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); 3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Apply relocation. 3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = GOT_S + A - GOT_ORG; 3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PLT32: PLT(S) + A - P 3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86RelocationFactory::Result plt32(Relocation& pReloc, 3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory& pParent) 3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // PLT_S depends on if there is a PLT entry. 3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory::Address PLT_S; 391affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT)) 3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLT_S = helper_PLT(pReloc, pParent); 3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else 3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao PLT_S = pReloc.symValue(); 3955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 3965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao X86RelocationFactory::Address P = pReloc.place(pParent.getLayout()); 3975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = PLT_S + A - P; 3985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return X86RelocationFactory::OK; 3995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 400