15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- MipsRelocationFactory.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/ELF.h> 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Layout.h> 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/OutputRelocSection.h> 14affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFactory.h" 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFunctions.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//===----------------------------------------------------------------------===// 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaotypedef RelocationFactory::Result (*ApplyFunctionType)(Relocation&, 2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const MCLDInfo& pLDInfo, 2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao MipsRelocationFactory&); 3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple 3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ApplyFunctionType func; 3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = { 4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao DECL_MIPS_APPLY_RELOC_FUNC_PTRS 4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MipsRelocationFactory 4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::MipsRelocationFactory(size_t pNum, 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& pParent) 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : RelocationFactory(pNum), 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Target(pParent), 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AHL(0) 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoRelocationFactory::Result 5667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoMipsRelocationFactory::applyRelocation(Relocation& pRelocation, 5767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const MCLDInfo& pLDInfo) 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) { 63affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::unknown_relocation) << (int)type 64affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << pRelocation.symInfo()->name(); 6567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return Unknown; 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 6967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[type].func(pRelocation, pLDInfo, *this); 7067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* MipsRelocationFactory::getName(Relocation::Type pType) const 7367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 7467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[pType].name; 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 7867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp"; 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc. 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc) 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode()); 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (NULL != reloc) 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (llvm::ELF::R_MIPS_LO16 == reloc->type() && 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc->symInfo() == pReloc.symInfo()) 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return reloc; 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc = static_cast<Relocation*>(reloc->getNextNode()); 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp. 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc) 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const ResolveInfo* rsym = pReloc.symInfo(); 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0 == strcmp(GP_DISP_NAME, rsym->name()); 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent) 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pParent.getTarget().getGOT().getSection().addr() + 0x7FF0; 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoGOTEntry& helper_GetGOTEntry(Relocation& pReloc, 115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsRelocationFactory& pParent, 116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool& pExist, int32_t value) 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang GOTEntry& got_entry = *got.getEntry(*rsym, pExist); 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pExist) 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return got_entry; 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this GOT entry, we should initialize it. 129affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!(got.isLocal(rsym) && rsym->type() == ResolveInfo::Section)) { 130affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & MipsGNULDBackend::ReserveGot) { 131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang got_entry.setContent(pReloc.symValue()); 132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 134cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_got); 135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return got_entry; 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc, 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 145affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool exist; 146affc150dc44fab1911775a49636d0ce85333b634Zonr Chang GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0); 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0; 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc) 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 || 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) && 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pLoReloc.type() == llvm::ELF::R_MIPS_LO16 && 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "Incorrect type of relocation for AHL calculation"); 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Note the addend is section symbol offset here 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert (pHiReloc.addend() == pLoReloc.addend()); 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHI = pHiReloc.target(); 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t ALO = pLoReloc.target(); 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + pLoReloc.addend(); 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return AHL; 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 173affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelDyn().getEntry(*rsym, false, exist); 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_MIPS_REL32); 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 181affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 182affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 183affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord S = pReloc.symValue(); 184affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 185affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (got.isLocal(rsym)) { 186affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(NULL); 187affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A + S; 188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 190affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(rsym); 191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Don't add symbol value that will be resolved by the dynamic linker 192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A; 193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation // 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result none(Relocation& pReloc, 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result abs32(Relocation& pReloc, 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 217affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 218affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord S = pReloc.symValue(); 219affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 220affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 221affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(pReloc.targetRef().frag())); 222affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != target_sect); 223affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 224affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 227affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return MipsRelocationFactory::OK; 228affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 229affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveRel) { 2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, pParent); 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 233affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return MipsRelocationFactory::OK; 234affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (S + A); 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16: 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: ((AHL + S) - (short)(AHL + S)) >> 16 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result hi16(Relocation& pReloc, 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16"); 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t P = pReloc.place(pParent.getLayout()); 2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16; 2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + S) - (int16_t)(AHL + S)) >> 16; 2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16: 2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: AHL + S 2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : AHL + GP - P + 4 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result lo16(Relocation& pReloc, 2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t P = pReloc.place(pParent.getLayout()); 2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 286affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t AHL = pParent.getAHL(); 2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = AHL + GP - P + 4; 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 291affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // The previous AHL may be for other hi/lo pairs. 292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // We need to calcuate the lo part now. It is easy. 293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to ALO. 294affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend(); 295affc150dc44fab1911775a49636d0ce85333b634Zonr Chang res = ALO + S; 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16: 3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local : G (calculate AHL and put high 16 bit to GOT) 3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// external: G 3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result got16(Relocation& pReloc, 3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::Address G = 0; 3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->isLocal()) { 3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16"); 3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = (AHL + S + 0x8000) & 0xFFFF0000; 325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool exist; 326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res); 327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(res); 329affc150dc44fab1911775a49636d0ce85333b634Zonr Chang G = pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0; 330affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 331affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 332affc150dc44fab1911775a49636d0ce85333b634Zonr Chang G = helper_GetGOTOffset(pReloc, pParent); 3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G 3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result call16(Relocation& pReloc, 3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent); 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP 3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result gprel32(Relocation& pReloc, 3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 361affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to A. 362affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t A = pReloc.target() + pReloc.addend(); 3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // llvm does not emits SHT_MIPS_REGINFO section. 3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Assume that GP0 is zero. 3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (A + S - GP) & 0xFFFFFFFF; 3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 372