MipsRelocator.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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> 1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FragmentLinker.h> 13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Target/OutputRelocSection.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 MipsRelocationFactory&); 2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple 3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ApplyFunctionType func; 3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = { 4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao DECL_MIPS_APPLY_RELOC_FUNC_PTRS 4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MipsRelocationFactory 4567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::MipsRelocationFactory(size_t pNum, 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& pParent) 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : RelocationFactory(pNum), 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Target(pParent), 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AHL(0) 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoRelocationFactory::Result 5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoMipsRelocationFactory::applyRelocation(Relocation& pRelocation) 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) { 6167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return Unknown; 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return ApplyFunctions[type].func(pRelocation, *this); 6667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* MipsRelocationFactory::getName(Relocation::Type pType) const 6967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 7067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[pType].name; 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 7467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp"; 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc. 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc) 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode()); 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (NULL != reloc) 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (llvm::ELF::R_MIPS_LO16 == reloc->type() && 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc->symInfo() == pReloc.symInfo()) 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return reloc; 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc = static_cast<Relocation*>(reloc->getNextNode()); 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp. 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc) 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const ResolveInfo* rsym = pReloc.symInfo(); 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0 == strcmp(GP_DISP_NAME, rsym->name()); 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent) 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return pParent.getTarget().getGOT().addr() + 0x7FF0; 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoGOT::Entry& helper_GetGOTEntry(Relocation& pReloc, 111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsRelocationFactory& pParent, 112affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool& pExist, int32_t value) 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) { 12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Local section symbols consume local got entries. 12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got.consumeLocal(); 12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != got_entry) { 12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // found a mapping, then return the mapped entry immediately 12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // not found 13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (got.isLocal(rsym)) 13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = got.consumeLocal(); 13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = got.consumeGlobal(); 13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this GOT entry, we should initialize it. 13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveGot) { 14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry->setContent(pReloc.symValue()); 14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_got); 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc, 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 153affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool exist; 15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0); 15522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return got_entry.getOffset() - 0x7FF0; 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc) 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 || 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) && 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pLoReloc.type() == llvm::ELF::R_MIPS_LO16 && 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "Incorrect type of relocation for AHL calculation"); 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Note the addend is section symbol offset here 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert (pHiReloc.addend() == pLoReloc.addend()); 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHI = pHiReloc.target(); 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t ALO = pLoReloc.target(); 17122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + 17222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pLoReloc.addend(); 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return AHL; 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 182affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_MIPS_REL32); 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 190affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord S = pReloc.symValue(); 191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (got.isLocal(rsym)) { 193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(NULL); 194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A + S; 195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(rsym); 198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Don't add symbol value that will be resolved by the dynamic linker 199affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A; 200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation // 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result none(Relocation& pReloc, 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result abs32(Relocation& pReloc, 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 222affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 223affc150dc44fab1911775a49636d0ce85333b634Zonr Chang RelocationFactory::DWord S = pReloc.symValue(); 224affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 22522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 227affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 22822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 229affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 230affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return MipsRelocationFactory::OK; 231affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 232affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveRel) { 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, pParent); 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return MipsRelocationFactory::OK; 237affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 239affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (S + A); 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16: 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: ((AHL + S) - (short)(AHL + S)) >> 16 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result hi16(Relocation& pReloc, 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16"); 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 26022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t P = pReloc.place(); 2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16; 2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + S) - (int16_t)(AHL + S)) >> 16; 2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16: 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: AHL + S 2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : AHL + GP - P + 4 2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result lo16(Relocation& pReloc, 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 28522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t P = pReloc.place(); 2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 287affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t AHL = pParent.getAHL(); 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = AHL + GP - P + 4; 2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // The previous AHL may be for other hi/lo pairs. 293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // We need to calcuate the lo part now. It is easy. 294affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to ALO. 295affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend(); 296affc150dc44fab1911775a49636d0ce85333b634Zonr Chang res = ALO + S; 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16: 3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local : G (calculate AHL and put high 16 bit to GOT) 3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// external: G 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result got16(Relocation& pReloc, 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; 32622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res); 327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(res); 32922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao G = got_entry.getOffset() - 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 MipsRelocationFactory& pParent) 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent); 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result gprel32(Relocation& pReloc, 3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 359affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to A. 360affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t A = pReloc.target() + pReloc.addend(); 3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // llvm does not emits SHT_MIPS_REGINFO section. 3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Assume that GP0 is zero. 3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (A + S - GP) & 0xFFFFFFFF; 3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 370