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> 14f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LinkerConfig.h> 15f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/IRBuilder.h> 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 17d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsRelocator.h" 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFunctions.h" 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 2367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables 2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 28d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaotypedef Relocator::Result (*ApplyFunctionType)(Relocation&, MipsRelocator&); 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; 366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = { 4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao DECL_MIPS_APPLY_RELOC_FUNC_PTRS 4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 45d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// MipsRelocator 4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 47f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsRelocator::MipsRelocator(MipsGNULDBackend& pParent, 48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LinkerConfig& pConfig) 49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines : Relocator(pConfig), 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Target(pParent), 51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_pApplyingInput(NULL), 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AHL(0) 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 56d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result 57d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::applyRelocation(Relocation& pRelocation) 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) { 6267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return Unknown; 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return ApplyFunctions[type].func(pRelocation, *this); 6767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 69d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaoconst char* MipsRelocator::getName(Relocation::Type pType) const 7067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{ 7167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return ApplyFunctions[pType].name; 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size MipsRelocator::getSize(Relocation::Type pType) const 756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return ApplyFunctions[pType].size; 776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanRelocation(Relocation& pReloc, 80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines LDSection& pSection) 83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation"); 87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Skip relocation against _gp_disp 89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (NULL != getTarget().getGpDispSymbol()) { 90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (pReloc.symInfo() == getTarget().getGpDispSymbol()->resolveInfo()) 91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 93f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 94f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pReloc.updateAddend(); 95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines assert(NULL != pSection.getLink()); 97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // We test isLocal or if pInputSym is not a dynamic symbol 101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn() 102f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Don't put undef symbols into local entries. 103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if ((rsym->isLocal() || !getTarget().isDynamicSymbol(*rsym) || 104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines !rsym->isDyn()) && !rsym->isUndef()) 105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines scanLocalReloc(pReloc, pBuilder, pSection); 106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines scanGlobalReloc(pReloc, pBuilder, pSection); 108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // check if we shoule issue undefined reference for the relocation target 110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // symbol 111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::undefined_reference) << rsym->name(); 113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::initializeScan(Input& pInput) 116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().initializeScan(pInput); 118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::finalizeScan(Input& pInput) 122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().finalizeScan(pInput); 124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::initializeApply(Input& pInput) 128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_pApplyingInput = &pInput; 130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 133f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsRelocator::finalizeApply(Input& pInput) 134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 135f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_pApplyingInput = NULL; 136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 137f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 138f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 139f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanLocalReloc(Relocation& pReloc, 140f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LDSection& pSection) 142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch (pReloc.type()){ 146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_NONE: 147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_16: 148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_32: 150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (LinkerConfig::DynObj == config().codeGenType()) { 151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // TODO: (simon) The gold linker does not create an entry in .rel.dyn 152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // section if the symbol section flags contains SHF_EXECINSTR. 153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 1. Find the reason of this condition. 154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 2. Check this condition here. 155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Remeber this rsym is a local GOT entry (as if it needs an entry). 160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Actually we don't allocate an GOT entry. 161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().setLocal(rsym); 162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_REL32: 165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_26: 166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HI16: 167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_LO16: 168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_PC16: 169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SHIFT5: 170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SHIFT6: 171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_64: 172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_PAGE: 173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_OFST: 174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SUB: 175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_INSERT_A: 176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_INSERT_B: 177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_DELETE: 178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HIGHER: 179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HIGHEST: 180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SCN_DISP: 181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_REL16: 182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_ADD_IMMEDIATE: 183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_PJUMP: 184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_RELGOT: 185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_JALR: 186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GLOB_DAT: 187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_COPY: 188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_JUMP_SLOT: 189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT16: 191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL16: 192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_HI16: 193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL_HI16: 194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_LO16: 195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL_LO16: 196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().getGOT().reserveLocalEntry(*rsym)) { 197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().getGOT().hasMultipleGOT()) 198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Remeber this rsym is a local GOT entry 200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().setLocal(rsym); 201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GPREL32: 204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GPREL16: 205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_LITERAL: 206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_DISP: 207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPMOD32: 209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL32: 210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPMOD64: 211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL64: 212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_GD: 213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_LDM: 214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL_HI16: 215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL_LO16: 216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_GOTTPREL: 217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL32: 218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL64: 219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL_HI16: 220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL_LO16: 221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 222f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::unknown_relocation) << (int)pReloc.type() 224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << pReloc.symInfo()->name(); 225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanGlobalReloc(Relocation& pReloc, 229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LDSection& pSection) 231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines switch (pReloc.type()){ 235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_NONE: 236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_INSERT_A: 237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_INSERT_B: 238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_DELETE: 239f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPMOD64: 240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL64: 241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_REL16: 242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_ADD_IMMEDIATE: 243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_PJUMP: 244f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_RELGOT: 245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL64: 246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 247f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_32: 248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_64: 249f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HI16: 250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_LO16: 251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().symbolNeedsDynRel(*rsym, false, true)) { 252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Remeber this rsym is a global GOT entry (as if it needs an entry). 257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Actually we don't allocate an GOT entry. 258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().setGlobal(rsym); 259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT16: 262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL16: 263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_DISP: 264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_HI16: 265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL_HI16: 266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_LO16: 267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL_LO16: 268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_PAGE: 269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_OFST: 270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().getGOT().reserveGlobalEntry(*rsym)) { 271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().getGOT().hasMultipleGOT()) 272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Remeber this rsym is a global GOT entry 274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getGOT().setGlobal(rsym); 275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_LITERAL: 278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GPREL32: 279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::invalid_global_relocation) << (int)pReloc.type() 280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << pReloc.symInfo()->name(); 281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GPREL16: 283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_26: 285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_PC16: 286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_16: 288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SHIFT5: 289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SHIFT6: 290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SUB: 291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HIGHER: 292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HIGHEST: 293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SCN_DISP: 294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL32: 296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_GD: 297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_LDM: 298f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL_HI16: 299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL_LO16: 300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_GOTTPREL: 301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL32: 302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL_HI16: 303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL_LO16: 304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_REL32: 306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_JALR: 308f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_COPY: 310f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GLOB_DAT: 311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_JUMP_SLOT: 312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::dynamic_relocation) << (int)pReloc.type(); 313f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines fatal(diag::unknown_relocation) << (int)pReloc.type() 316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines << pReloc.symInfo()->name(); 317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 32067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 32167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function 32267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp"; 3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc. 3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc) 3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode()); 3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (NULL != reloc) 3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (llvm::ELF::R_MIPS_LO16 == reloc->type() && 3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc->symInfo() == pReloc.symInfo()) 3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return reloc; 3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc = static_cast<Relocation*>(reloc->getNextNode()); 3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp. 3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc) 3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const ResolveInfo* rsym = pReloc.symInfo(); 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0 == strcmp(GP_DISP_NAME, rsym->name()); 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 350d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGP(MipsRelocator& pParent) 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return pParent.getTarget().getGOT().getGPAddr(pParent.getApplyingInput()); 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid helper_SetupRelDynForGOTEntry(MipsGOTEntry& got_entry, 357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocation& pReloc, 358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym, 359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsRelocator& pParent) 360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{ 361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsGNULDBackend& ld_backend = pParent.getTarget(); 362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setType(llvm::ELF::R_MIPS_REL32); 365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.targetRef() = *FragmentRef::Create(got_entry, 0); 366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rel_entry.setSymInfo(rsym); 367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesstatic 370f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsGOTEntry& helper_GetGOTEntry(Relocation& pReloc, MipsRelocator& pParent) 3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 375affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsGOTEntry* got_entry; 3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 37822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) { 37922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Local section symbols consume local got entries. 380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines got_entry = got.consumeLocal(); 381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (got.isPrimaryGOTConsumed()) 382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_SetupRelDynForGOTEntry(*got_entry, pReloc, NULL, pParent); 383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return *got_entry; 38422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 38522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines got_entry = got.lookupEntry(rsym); 38722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != got_entry) { 38822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // found a mapping, then return the mapped entry immediately 38922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 39022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 39222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // not found 39322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (got.isLocal(rsym)) 39422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = got.consumeLocal(); 39522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 39622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao got_entry = got.consumeGlobal(); 39722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines got.recordEntry(rsym, got_entry); 3995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this GOT entry, we should initialize it. 401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!got.isLocal(rsym) || ResolveInfo::Section != rsym->type()) { 402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (!got.isPrimaryGOTConsumed()) 403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines got_entry->setValue(pReloc.symValue()); 4045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (got.isPrimaryGOTConsumed()) 407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines helper_SetupRelDynForGOTEntry(*got_entry, pReloc, 408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines got.isLocal(rsym) ? NULL : rsym, pParent); 409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 41022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 4115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 414d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Address helper_GetGOTOffset(Relocation& pReloc, 415d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao MipsRelocator& pParent) 4165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsGNULDBackend& ld_backend = pParent.getTarget(); 418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsGOT& got = ld_backend.getGOT(); 419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent); 420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return got.getGPRelOffset(pParent.getApplyingInput(), got_entry); 4215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 4245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc) 4255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 || 4275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) && 4285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pLoReloc.type() == llvm::ELF::R_MIPS_LO16 && 4295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "Incorrect type of relocation for AHL calculation"); 4305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Note the addend is section symbol offset here 4325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert (pHiReloc.addend() == pLoReloc.addend()); 4335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHI = pHiReloc.target(); 4355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t ALO = pLoReloc.target(); 43622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + 43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pLoReloc.addend(); 4385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return AHL; 4395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 442d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, MipsRelocator& pParent) 4435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 4455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 446affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MipsGOT& got = ld_backend.getGOT(); 4475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 4495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_MIPS_REL32); 4515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 452affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 453d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 454d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 455affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 456affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (got.isLocal(rsym)) { 457affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(NULL); 458affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A + S; 459affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 460affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 461affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(rsym); 462affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Don't add symbol value that will be resolved by the dynamic linker 463affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = A; 464affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 4655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 4685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation // 4695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 4705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type 4725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 473d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result none(Relocation& pReloc, MipsRelocator& pParent) 4745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 475d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 4765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 4775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A 4795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 480d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result abs32(Relocation& pReloc, MipsRelocator& pParent) 4815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 484d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord A = pReloc.target() + pReloc.addend(); 485d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::DWord S = pReloc.symValue(); 486affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 488affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // If the flag of target section is not ALLOC, we will not scan this relocation 489affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 49022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 491affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = S + A; 492d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 493affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 494affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 495f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & MipsRelocator::ReserveRel) { 4965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, pParent); 4975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 498d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 499affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 5005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 501affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pReloc.target() = (S + A); 5025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 503d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 5045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16: 5075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: ((AHL + S) - (short)(AHL + S)) >> 16 5085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 5095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 510d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result hi16(Relocation& pReloc, MipsRelocator& pParent) 5115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 5125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 5135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16"); 5145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 5165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 5175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 5195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 52122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t P = pReloc.place(); 5225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 5235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16; 5245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 5265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 5275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + S) - (int16_t)(AHL + S)) >> 16; 5285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 5315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 5325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 533d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 5345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16: 5375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: AHL + S 5385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : AHL + GP - P + 4 5395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 540d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result lo16(Relocation& pReloc, MipsRelocator& pParent) 5415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 5425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 5435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 54522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao int32_t P = pReloc.place(); 5465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 547affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t AHL = pParent.getAHL(); 5485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = AHL + GP - P + 4; 5495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 5515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 552affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // The previous AHL may be for other hi/lo pairs. 553affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // We need to calcuate the lo part now. It is easy. 554affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to ALO. 555affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend(); 556affc150dc44fab1911775a49636d0ce85333b634Zonr Chang res = ALO + S; 5575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 5605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 5615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 562d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 5635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16: 5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local : G (calculate AHL and put high 16 bit to GOT) 5675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// external: G 5685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 569d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result got16(Relocation& pReloc, MipsRelocator& pParent) 5705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsGNULDBackend& ld_backend = pParent.getTarget(); 572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsGOT& got = ld_backend.getGOT(); 5735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 574d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = 0; 5755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->isLocal()) { 5775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 5785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16"); 5795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 5815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 5825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 5845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = (AHL + S + 0x8000) & 0xFFFF0000; 586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent); 587affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 588d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao got_entry.setValue(res); 589f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines G = got.getGPRelOffset(pParent.getApplyingInput(), got_entry); 590affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 591affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 592affc150dc44fab1911775a49636d0ce85333b634Zonr Chang G = helper_GetGOTOffset(pReloc, pParent); 5935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 5965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 5975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 598d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 599d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 600d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 601d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTHI16: 602d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// external: (G - (short)G) >> 16 + A 603d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic 604d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gothi16(Relocation& pReloc, MipsRelocator& pParent) 605d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{ 606d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao int32_t res = 0; 607d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 608d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 609d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao int32_t A = pReloc.target() + pReloc.addend(); 610d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 611d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao res = (G - (int16_t)G) >> (16 + A); 612d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 613d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() &= 0xFFFF0000; 614d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 615d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 616d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 617d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 618d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 619d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTLO16: 620d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// external: G & 0xffff 621d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic 622d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gotlo16(Relocation& pReloc, MipsRelocator& pParent) 623d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{ 624d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 625d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 626d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() &= 0xFFFF0000; 627d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 628d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 629d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 6305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 6315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G 6335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 634d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result call16(Relocation& pReloc, MipsRelocator& pParent) 6355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 636d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocator::Address G = helper_GetGOTOffset(pReloc, pParent); 6375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 6405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 641d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 6435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP 6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 646d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsRelocator::Result gprel32(Relocation& pReloc, MipsRelocator& pParent) 6475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 648affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to A. 649affc150dc44fab1911775a49636d0ce85333b634Zonr Chang int32_t A = pReloc.target() + pReloc.addend(); 6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // llvm does not emits SHT_MIPS_REGINFO section. 6545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Assume that GP0 is zero. 6555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (A + S - GP) & 0xFFFFFFFF; 6565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 657d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return MipsRelocator::OK; 6585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 659d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 660