MipsRelocator.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
1d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===- MipsRelocator.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> 12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Target/OutputRelocSection.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 15d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsRelocator.h" 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFunctions.h" 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 2167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables 2267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 26d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaotypedef Relocator::Result (*ApplyFunctionType)(Relocation&, MipsRelocator&); 2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple 3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ApplyFunctionType func; 3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = { 3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao DECL_MIPS_APPLY_RELOC_FUNC_PTRS 4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 43d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// MipsRelocator 4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 45d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::MipsRelocator(MipsGNULDBackend& pParent) 46d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao : Relocator(), 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Target(pParent), 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AHL(0) 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 52d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result 53d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::applyRelocation(Relocation& pRelocation) 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) { 5967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return Unknown; 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return ApplyFunctions[type].func(pRelocation, *this); 6467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 66d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaoconst char* MipsRelocator::getName(Relocation::Type pType) const 6767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[pType].name; 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size MipsRelocator::getSize(Relocation::Type pType) const 726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return ApplyFunctions[pType].size; 746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 7767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function 7867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp"; 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc. 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc) 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode()); 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (NULL != reloc) 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (llvm::ELF::R_MIPS_LO16 == reloc->type() && 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc->symInfo() == pReloc.symInfo()) 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return reloc; 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc = static_cast<Relocation*>(reloc->getNextNode()); 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp. 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc) 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const ResolveInfo* rsym = pReloc.symInfo(); 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0 == strcmp(GP_DISP_NAME, rsym->name()); 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 106d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGP(MipsRelocator& pParent) 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return pParent.getTarget().getGOT().addr() + 0x7FF0; 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 112d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsGOTEntry& helper_GetGOTEntry(Relocation& pReloc, 113d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsRelocator& pParent, 114d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao bool& pExist, int32_t value) 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 119affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) { 12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Local section symbols consume local got entries. 12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got.consumeLocal(); 12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 126d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != got_entry) { 12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // found a mapping, then return the mapped entry immediately 12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // not found 13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (got.isLocal(rsym)) 13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = got.consumeLocal(); 13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = got.consumeGlobal(); 13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this GOT entry, we should initialize it. 14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveGot) { 142d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(pReloc.symValue()); 14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_got); 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 152d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGOTOffset(Relocation& pReloc, 153d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsRelocator& pParent) 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool exist; 156d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0); 15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return got_entry.getOffset() - 0x7FF0; 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc) 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 || 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) && 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pLoReloc.type() == llvm::ELF::R_MIPS_LO16 && 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "Incorrect type of relocation for AHL calculation"); 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Note the addend is section symbol offset here 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert (pHiReloc.addend() == pLoReloc.addend()); 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHI = pHiReloc.target(); 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t ALO = pLoReloc.target(); 17322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + 17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pLoReloc.addend(); 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return AHL; 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 179d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, MipsRelocator& pParent) 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 183affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_MIPS_REL32); 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 190d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 191d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (got.isLocal(rsym)) { 194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(NULL); 195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A + S; 196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(rsym); 199affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Don't add symbol value that will be resolved by the dynamic linker 200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A; 201affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation // 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 210d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result none(Relocation& pReloc, MipsRelocator& pParent) 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 212d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 217d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result abs32(Relocation& pReloc, MipsRelocator& pParent) 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 221d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 222d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 223affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 22422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 22722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 228affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 229d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 230affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 231affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveRel) { 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, pParent); 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 235d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 238affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (S + A); 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 240d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16: 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: ((AHL + S) - (short)(AHL + S)) >> 16 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 247d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result hi16(Relocation& pReloc, MipsRelocator& 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)) { 25822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t P = pReloc.place(); 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 270d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::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 277d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result lo16(Relocation& pReloc, MipsRelocator& pParent) 2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 28222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t P = pReloc.place(); 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 284affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t AHL = pParent.getAHL(); 2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = AHL + GP - P + 4; 2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 289affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // The previous AHL may be for other hi/lo pairs. 290affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // We need to calcuate the lo part now. It is easy. 291affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to ALO. 292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend(); 293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang res = ALO + S; 2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 299d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16: 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local : G (calculate AHL and put high 16 bit to GOT) 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// external: G 3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 306d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result got16(Relocation& pReloc, MipsRelocator& pParent) 3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 309d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = 0; 3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->isLocal()) { 3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16"); 3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = (AHL + S + 0x8000) & 0xFFFF0000; 321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool exist; 322d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res); 323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 324d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry.setValue(res); 32522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao G = got_entry.getOffset() - 0x7FF0; 326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang G = helper_GetGOTOffset(pReloc, pParent); 3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 334d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 335d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 336d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 337d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTHI16: 338d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// external: (G - (short)G) >> 16 + A 339d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic 340d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gothi16(Relocation& pReloc, MipsRelocator& pParent) 341d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{ 342d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao int32_t res = 0; 343d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 344d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 345d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao int32_t A = pReloc.target() + pReloc.addend(); 346d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 347d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao res = (G - (int16_t)G) >> (16 + A); 348d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 349d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() &= 0xFFFF0000; 350d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 351d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 352d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 353d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 354d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 355d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTLO16: 356d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// external: G & 0xffff 357d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic 358d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gotlo16(Relocation& pReloc, MipsRelocator& pParent) 359d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{ 360d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 361d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 362d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() &= 0xFFFF0000; 363d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 364d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 365d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G 3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 370d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result call16(Relocation& pReloc, MipsRelocator& pParent) 3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 372d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 377d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP 3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 382d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gprel32(Relocation& pReloc, MipsRelocator& pParent) 3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 384affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to A. 385affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t A = pReloc.target() + pReloc.addend(); 3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // llvm does not emits SHT_MIPS_REGINFO section. 3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Assume that GP0 is zero. 3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (A + S - GP) & 0xFFFFFFFF; 3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 393d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 395d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 396