MipsRelocator.cpp revision d0fbbb227051be16931a1aa9b4a7722ac039c698
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> 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 16d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsRelocator.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 27d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaotypedef Relocator::Result (*ApplyFunctionType)(Relocation&, MipsRelocator&); 2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple 3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ApplyFunctionType func; 3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 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 7167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 7267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp"; 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc. 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc) 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode()); 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (NULL != reloc) 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (llvm::ELF::R_MIPS_LO16 == reloc->type() && 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc->symInfo() == pReloc.symInfo()) 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return reloc; 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc = static_cast<Relocation*>(reloc->getNextNode()); 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp. 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc) 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const ResolveInfo* rsym = pReloc.symInfo(); 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0 == strcmp(GP_DISP_NAME, rsym->name()); 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 102d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGP(MipsRelocator& pParent) 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return pParent.getTarget().getGOT().addr() + 0x7FF0; 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 108d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsGOTEntry& helper_GetGOTEntry(Relocation& pReloc, 109d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsRelocator& pParent, 110d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao bool& pExist, int32_t value) 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) { 11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Local section symbols consume local got entries. 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got.consumeLocal(); 12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 122d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != got_entry) { 12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // found a mapping, then return the mapped entry immediately 12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // not found 12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (got.isLocal(rsym)) 13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = got.consumeLocal(); 13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = got.consumeGlobal(); 13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pParent.getSymGOTMap().record(*rsym, *got_entry); 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this GOT entry, we should initialize it. 13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveGot) { 138d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry->setValue(pReloc.symValue()); 13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fatal(diag::reserve_entry_number_mismatch_got); 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 148d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGOTOffset(Relocation& pReloc, 149d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsRelocator& pParent) 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool exist; 152d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0); 15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return got_entry.getOffset() - 0x7FF0; 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc) 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 || 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) && 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pLoReloc.type() == llvm::ELF::R_MIPS_LO16 && 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "Incorrect type of relocation for AHL calculation"); 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Note the addend is section symbol offset here 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert (pHiReloc.addend() == pLoReloc.addend()); 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHI = pHiReloc.target(); 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t ALO = pLoReloc.target(); 16922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + 17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pLoReloc.addend(); 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return AHL; 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 175d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, MipsRelocator& pParent) 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 179affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 18122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_MIPS_REL32); 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 185affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 186d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 187d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (got.isLocal(rsym)) { 190affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(NULL); 191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A + S; 192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(rsym); 195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Don't add symbol value that will be resolved by the dynamic linker 196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A; 197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation // 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 206d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result none(Relocation& pReloc, MipsRelocator& pParent) 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 208d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 213d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result abs32(Relocation& pReloc, MipsRelocator& pParent) 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 217d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 218d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 219affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 22022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 221affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 222affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 22322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 224affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 225d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 227affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveRel) { 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, pParent); 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 231d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 232affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 234affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (S + A); 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 236d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16: 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: ((AHL + S) - (short)(AHL + S)) >> 16 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 243d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result hi16(Relocation& pReloc, MipsRelocator& pParent) 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16"); 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 25422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t P = pReloc.place(); 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16; 2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + S) - (int16_t)(AHL + S)) >> 16; 2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 266d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16: 2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: AHL + S 2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : AHL + GP - P + 4 2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 273d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result lo16(Relocation& pReloc, MipsRelocator& pParent) 2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 27822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t P = pReloc.place(); 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 280affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t AHL = pParent.getAHL(); 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = AHL + GP - P + 4; 2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 285affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // The previous AHL may be for other hi/lo pairs. 286affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // We need to calcuate the lo part now. It is easy. 287affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to ALO. 288affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend(); 289affc150dc44fab1911775a49636d0ce85333b634Zonr Chang res = ALO + S; 2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 295d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16: 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local : G (calculate AHL and put high 16 bit to GOT) 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// external: G 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 302d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result got16(Relocation& pReloc, MipsRelocator& pParent) 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 305d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = 0; 3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->isLocal()) { 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16"); 3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = (AHL + S + 0x8000) & 0xFFFF0000; 317affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool exist; 318d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res); 319affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 320d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry.setValue(res); 32122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao G = got_entry.getOffset() - 0x7FF0; 322affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 324affc150dc44fab1911775a49636d0ce85333b634Zonr Chang G = helper_GetGOTOffset(pReloc, pParent); 3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 330d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 331d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 332d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 333d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTHI16: 334d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// external: (G - (short)G) >> 16 + A 335d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic 336d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gothi16(Relocation& pReloc, MipsRelocator& pParent) 337d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{ 338d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao int32_t res = 0; 339d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 340d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 341d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao int32_t A = pReloc.target() + pReloc.addend(); 342d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 343d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao res = (G - (int16_t)G) >> (16 + A); 344d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 345d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() &= 0xFFFF0000; 346d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 347d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 348d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 349d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 350d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 351d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTLO16: 352d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// external: G & 0xffff 353d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic 354d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gotlo16(Relocation& pReloc, MipsRelocator& pParent) 355d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{ 356d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 357d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 358d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() &= 0xFFFF0000; 359d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 360d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 361d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G 3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 366d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result call16(Relocation& pReloc, MipsRelocator& pParent) 3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 368d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 373d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP 3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 378d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gprel32(Relocation& pReloc, MipsRelocator& pParent) 3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 380affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to A. 381affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t A = pReloc.target() + pReloc.addend(); 3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // llvm does not emits SHT_MIPS_REGINFO section. 3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Assume that GP0 is zero. 3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (A + S - GP) & 0xFFFFFFFF; 3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 389d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 391d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 392