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//===----------------------------------------------------------------------===// 987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "MipsRelocator.h" 1087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "MipsRelocationFunctions.h" 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h" 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/OutputRelocSection.h" 1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h" 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/ADT/Twine.h> 2087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/Support/ELF.h> 2187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 2237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// MipsRelocationInfo 2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===// 2737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesclass MipsRelocationInfo { 2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines public: 2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines static bool HasSubType(const Relocation& pParent, Relocation::Type pType) { 3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (llvm::ELF::R_MIPS_NONE == pType) 3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return true; 3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 3387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines for (Relocation::Type type = pParent.type(); 3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::ELF::R_MIPS_NONE != (type & 0xff); 3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines type >>= 8) { 3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if ((type & 0xff) == pType) 3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return true; 3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return false; 4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines MipsRelocationInfo(Relocation& pParent, bool pIsRel) 4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines : m_Parent(&pParent), 4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Type(pParent.type()), 46b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines m_Addend(pIsRel ? pParent.target() : pParent.addend()), 4737b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Symbol(pParent.symValue()), 48b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines m_Result(pParent.target()) {} 4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 5037b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool isNone() const { return llvm::ELF::R_MIPS_NONE == type(); } 51b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines bool isFirst() const { return type() == (parent().type() & 0xff); } 5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool isLast() const { return llvm::ELF::R_MIPS_NONE == (m_Type >> 8); } 5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 5437b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocationInfo next() const { 55b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return MipsRelocationInfo(*m_Parent, m_Type >> 8, result(), result()); 5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines const Relocation& parent() const { return *m_Parent; } 5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 6037b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation& parent() { return *m_Parent; } 6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::Type type() const { return m_Type & 0xff; } 6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 6437b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::DWord A() const { return m_Addend; } 6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::DWord S() const { return m_Symbol; } 6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 6837b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::DWord P() const { return parent().place(); } 6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 7037b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::DWord result() const { return m_Result; } 7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::DWord& result() { return m_Result; } 7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 7437b74a387bb3993387029859c2d9d051c41c724eStephen Hines private: 7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation* m_Parent; 7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation::Type m_Type; 7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation::DWord m_Addend; 7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation::DWord m_Symbol; 7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation::DWord m_Result; 8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 81b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocationInfo(Relocation& pParent, Relocation::Type pType, 82b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Relocation::DWord pResult, Relocation::DWord pAddend) 8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines : m_Parent(&pParent), 8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Type(pType), 8537b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Addend(pAddend), 86b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines m_Symbol(0), 8737b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Result(pResult) {} 8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}; 8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 90b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic void helper_PLT_init(MipsRelocationInfo& pReloc, 91b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 92b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 93b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines assert(pParent.getSymPLTMap().lookUp(*rsym) == NULL && "PLT entry exists"); 94b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 95b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsGNULDBackend& backend = pParent.getTarget(); 96b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines PLTEntryBase* pltEntry = backend.getPLT().create(); 97b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pParent.getSymPLTMap().record(*rsym, *pltEntry); 98b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 99b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines assert(pParent.getSymGOTPLTMap().lookUp(*rsym) == NULL && 100b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines "PLT entry not exist, but DynRel entry exist!"); 101b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Fragment* gotpltEntry = backend.getGOTPLT().create(); 102b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pParent.getSymGOTPLTMap().record(*rsym, *gotpltEntry); 103b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 104b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Relocation* relEntry = backend.getRelPLT().create(); 105b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines relEntry->setType(llvm::ELF::R_MIPS_JUMP_SLOT); 106b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines relEntry->targetRef().assign(*gotpltEntry); 107b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines relEntry->setSymInfo(rsym); 108b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 109b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 110b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic Relocator::Address helper_get_PLT_address(ResolveInfo& pSym, 111b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 112b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym); 113b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines assert(plt_entry != NULL); 114b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 115b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 116b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===// 11867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables 11967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function 12387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinestypedef Relocator::Result (*ApplyFunctionType)(MipsRelocationInfo&, 12487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines MipsRelocator& pParent); 12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 12667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions 12737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstruct ApplyFunctionTriple { 12867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao ApplyFunctionType func; 12967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao unsigned int type; 13067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao const char* name; 1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int size; 13267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}; 13367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 13467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions 13567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = { 13637b74a387bb3993387029859c2d9d051c41c724eStephen Hines DECL_MIPS_APPLY_RELOC_FUNC_PTRS}; 13767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 13867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// MipsRelocator 14067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===----------------------------------------------------------------------===// 141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesMipsRelocator::MipsRelocator(MipsGNULDBackend& pParent, 142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const LinkerConfig& pConfig) 14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines : Relocator(pConfig), 14437b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_Target(pParent), 14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_pApplyingInput(NULL), 14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_CurrentLo16Reloc(NULL) { 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 14937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result MipsRelocator::applyRelocation(Relocation& pReloc) { 15087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // If m_CurrentLo16Reloc is not NULL we are processing 15187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // postponed relocation. Otherwise check relocation type 15287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // and postpone it for later handling. 15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (m_CurrentLo16Reloc == NULL && isPostponed(pReloc)) { 15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines postponeRelocation(pReloc); 15587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return OK; 15687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 15787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 15837b74a387bb3993387029859c2d9d051c41c724eStephen Hines for (MipsRelocationInfo info(pReloc, isRel()); !info.isNone(); 15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines info = info.next()) { 16087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (info.type() >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) 16187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return Unknown; 16287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 16337b74a387bb3993387029859c2d9d051c41c724eStephen Hines const ApplyFunctionTriple& triple = ApplyFunctions[info.type()]; 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 16587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Result res = triple.func(info, *this); 16687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (OK != res) 16787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return res; 16887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 16987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (info.isLast()) { 17087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - triple.size); 17187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.target() &= ~mask; 17287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.target() |= info.result() & mask; 17387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 17687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return OK; 17767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao} 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 17937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst char* MipsRelocator::getName(Relocation::Type pType) const { 18087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return ApplyFunctions[pType & 0xff].name; 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsRelocator::scanRelocation(Relocation& pReloc, 184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines Module& pModule, 18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& pSection, 18737b74a387bb3993387029859c2d9d051c41c724eStephen Hines Input& pInput) { 188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // rsym - The relocation target symbol 189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 19037b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(rsym != NULL && 19137b74a387bb3993387029859c2d9d051c41c724eStephen Hines "ResolveInfo of relocation not set while scanRelocation"); 192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // Skip relocation against _gp_disp 19437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (getTarget().getGpDispSymbol() != NULL && 19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym == getTarget().getGpDispSymbol()->resolveInfo()) 19687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return; 197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 19837b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(pSection.getLink() != NULL); 19937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0) 200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return; 201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 20237b74a387bb3993387029859c2d9d051c41c724eStephen Hines for (MipsRelocationInfo info(pReloc, isRel()); !info.isNone(); 20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines info = info.next()) { 20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // We test isLocal or if pInputSym is not a dynamic symbol 20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn() 20687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Don't put undef symbols into local entries. 20787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (isLocalReloc(*rsym)) 20887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines scanLocalReloc(info, pBuilder, pSection); 20987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 21087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines scanGlobalReloc(info, pBuilder, pSection); 21187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 21287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (getTarget().needsLA25Stub(info.type(), info.parent().symInfo())) 21387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().addNonPICBranchSym(pReloc.symInfo()); 21487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 21687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Check if we should issue undefined reference 21787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // for the relocation target symbol. 218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 21987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines issueUndefRef(pReloc, pSection, pInput); 220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 22237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::initializeScan(Input& pInput) { 22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (LinkerConfig::Object != config().codeGenType()) 22487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().getGOT().initializeScan(pInput); 225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 22837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::finalizeScan(Input& pInput) { 22987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (LinkerConfig::Object != config().codeGenType()) 23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getTarget().getGOT().finalizeScan(pInput); 231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 23437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::initializeApply(Input& pInput) { 235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_pApplyingInput = &pInput; 236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 23937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::finalizeApply(Input& pInput) { 240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_pApplyingInput = NULL; 241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 24487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::scanLocalReloc(MipsRelocationInfo& pReloc, 245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 24637b74a387bb3993387029859c2d9d051c41c724eStephen Hines const LDSection& pSection) { 24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 24937b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_NONE: 251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_16: 252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_32: 25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_MIPS_64: 255b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pReloc.isFirst() && LinkerConfig::DynObj == config().codeGenType()) { 256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // TODO: (simon) The gold linker does not create an entry in .rel.dyn 257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // section if the symbol section flags contains SHF_EXECINSTR. 258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 1. Find the reason of this condition. 259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // 2. Check this condition here. 260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_REL32: 266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_26: 267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HI16: 268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_LO16: 269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SHIFT5: 270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SHIFT6: 271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SUB: 272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_INSERT_A: 273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_INSERT_B: 274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_DELETE: 275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HIGHER: 276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HIGHEST: 277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SCN_DISP: 278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_REL16: 279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_ADD_IMMEDIATE: 280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_PJUMP: 281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_RELGOT: 282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_JALR: 283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GLOB_DAT: 284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_COPY: 285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_JUMP_SLOT: 286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT16: 288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL16: 289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_HI16: 290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL_HI16: 291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_LO16: 292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL_LO16: 29387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_MIPS_GOT_DISP: 29487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_MIPS_GOT_PAGE: 29587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_MIPS_GOT_OFST: 29637b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (getTarget() 29737b74a387bb3993387029859c2d9d051c41c724eStephen Hines .getGOT() 29837b74a387bb3993387029859c2d9d051c41c724eStephen Hines .reserveLocalEntry(*rsym, pReloc.type(), pReloc.A())) { 299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().getGOT().hasMultipleGOT()) 300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GPREL32: 304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GPREL16: 305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_LITERAL: 306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 307b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_TLS_GD: 308b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().getGOT().reserveTLSGdEntry(*rsym); 309b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 310b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines break; 311b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_TLS_LDM: 312b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().getGOT().reserveTLSLdmEntry(); 313b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 314b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines break; 315b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_TLS_GOTTPREL: 316b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().getGOT().reserveTLSGotEntry(*rsym); 317b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 318b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines break; 319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPMOD32: 320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL32: 321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPMOD64: 322f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL64: 323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL_HI16: 324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL_LO16: 325f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL32: 326f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL64: 327f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL_HI16: 328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL_LO16: 329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 330b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC16: 33187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_MIPS_PC32: 332b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC18_S3: 333b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC19_S2: 334b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC21_S2: 335b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC26_S2: 336b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PCHI16: 337b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PCLO16: 33887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines break; 339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 34037b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::unknown_relocation) << static_cast<int>(pReloc.type()) 34137b74a387bb3993387029859c2d9d051c41c724eStephen Hines << rsym->name(); 342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 34587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsRelocator::scanGlobalReloc(MipsRelocationInfo& pReloc, 346f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines IRBuilder& pBuilder, 34737b74a387bb3993387029859c2d9d051c41c724eStephen Hines const LDSection& pSection) { 34887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 349b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines bool hasPLT = rsym->reserved() & ReservePLT; 350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 35137b74a387bb3993387029859c2d9d051c41c724eStephen Hines switch (pReloc.type()) { 352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_NONE: 353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_INSERT_A: 354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_INSERT_B: 355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_DELETE: 356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPMOD64: 357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL64: 358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_REL16: 359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_ADD_IMMEDIATE: 360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_PJUMP: 361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_RELGOT: 362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL64: 363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_32: 365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_64: 366b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pReloc.isFirst() && 367b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().symbolNeedsDynRel(*rsym, hasPLT, true)) { 368b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().getRelDyn().reserveEntry(); 369b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 370b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 371b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (!getTarget().symbolFinalValueIsKnown(*rsym)) 372b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().getGOT().reserveGlobalEntry(*rsym); 373b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } 374b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines break; 375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HI16: 376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_LO16: 377b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (getTarget().symbolNeedsDynRel(*rsym, hasPLT, true) || 378b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().symbolNeedsCopyReloc(pReloc.parent(), *rsym)) { 379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().getRelDyn().reserveEntry(); 380b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines LDSymbol& cpySym = defineSymbolforCopyReloc(pBuilder, *rsym); 381b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines addCopyReloc(*cpySym.resolveInfo()); 382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT16: 385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL16: 386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_DISP: 387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_HI16: 388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL_HI16: 389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_LO16: 390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_CALL_LO16: 391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_PAGE: 392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GOT_OFST: 393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().getGOT().reserveGlobalEntry(*rsym)) { 394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (getTarget().getGOT().hasMultipleGOT()) 395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_LITERAL: 399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GPREL32: 40037b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::invalid_global_relocation) << static_cast<int>(pReloc.type()) 40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines << rsym->name(); 402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GPREL16: 404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_26: 40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Create a PLT entry if the symbol requires it and does not have it. 407b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (getTarget().symbolNeedsPLT(*rsym) && !hasPLT) { 408b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines helper_PLT_init(pReloc, *this); 40987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 41087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 41187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines break; 412f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_16: 413f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SHIFT5: 414f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SHIFT6: 415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SUB: 416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HIGHER: 417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_HIGHEST: 418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_SCN_DISP: 419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_GD: 421b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().getGOT().reserveTLSGdEntry(*rsym); 422b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 423b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines break; 424f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_LDM: 425b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().getGOT().reserveTLSLdmEntry(); 426b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 427b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines break; 428b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_TLS_GOTTPREL: 429b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().getGOT().reserveTLSGotEntry(*rsym); 430b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getTarget().checkAndSetHasTextRel(*pSection.getLink()); 431b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines break; 432b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL32: 433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL_HI16: 434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_DTPREL_LO16: 435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL32: 436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL_HI16: 437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_TLS_TPREL_LO16: 438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_REL32: 440f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_JALR: 441b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC16: 44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines case llvm::ELF::R_MIPS_PC32: 443b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC18_S3: 444b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC19_S2: 445b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC21_S2: 446b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PC26_S2: 447b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PCHI16: 448b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines case llvm::ELF::R_MIPS_PCLO16: 449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_COPY: 451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_GLOB_DAT: 452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines case llvm::ELF::R_MIPS_JUMP_SLOT: 45337b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::dynamic_relocation) << static_cast<int>(pReloc.type()); 454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines break; 455f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines default: 45637b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::unknown_relocation) << static_cast<int>(pReloc.type()) 45737b74a387bb3993387029859c2d9d051c41c724eStephen Hines << rsym->name(); 458f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 46137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isPostponed(const Relocation& pReloc) const { 462b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (isN64ABI()) 463b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return false; 464b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 465b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_HI16) || 466b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_PCHI16)) 46787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return true; 4685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 46987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_GOT16) && 47087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.symInfo()->isLocal()) 47187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return true; 47287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 47387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return false; 47487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 47587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 47637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::addCopyReloc(ResolveInfo& pSym) { 47787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocation& relEntry = *getTarget().getRelDyn().consumeEntry(); 47887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines relEntry.setType(llvm::ELF::R_MIPS_COPY); 47987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(pSym.outSymbol()->hasFragRef()); 48087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines relEntry.targetRef().assign(*pSym.outSymbol()->fragRef()); 48187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines relEntry.setSymInfo(&pSym); 48287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 48487f34658dec9097d987d254a990ea7f311bfc95fStephen HinesLDSymbol& MipsRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 48537b74a387bb3993387029859c2d9d051c41c724eStephen Hines const ResolveInfo& pSym) { 48687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Get or create corresponding BSS LDSection 48787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ELFFileFormat* fileFormat = getTarget().getOutputFormat(); 48837b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSection* bssSectHdr = ResolveInfo::ThreadLocal == pSym.type() 48937b74a387bb3993387029859c2d9d051c41c724eStephen Hines ? &fileFormat->getTBSS() 49037b74a387bb3993387029859c2d9d051c41c724eStephen Hines : &fileFormat->getBSS(); 49187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 49287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Get or create corresponding BSS SectionData 49337b74a387bb3993387029859c2d9d051c41c724eStephen Hines SectionData* bssData = bssSectHdr->hasSectionData() 49437b74a387bb3993387029859c2d9d051c41c724eStephen Hines ? bssSectHdr->getSectionData() 49537b74a387bb3993387029859c2d9d051c41c724eStephen Hines : IRBuilder::CreateSectionData(*bssSectHdr); 49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 49787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Determine the alignment by the symbol value 49887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // FIXME: here we use the largest alignment 49987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t addrAlign = config().targets().bitclass() / 8; 50087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 50187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Allocate space in BSS for the copy symbol 50287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 50387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t size = ObjectBuilder::AppendFragment(*frag, *bssData, addrAlign); 50487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bssSectHdr->setSize(bssSectHdr->size() + size); 50587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 50687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Change symbol binding to Global if it's a weak symbol 50787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 50887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (binding == ResolveInfo::Weak) 50987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines binding = ResolveInfo::Global; 51087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 51187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Define the copy symbol in the bss section and resolve it 51287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSymbol* cpySym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 51337b74a387bb3993387029859c2d9d051c41c724eStephen Hines pSym.name(), 51437b74a387bb3993387029859c2d9d051c41c724eStephen Hines (ResolveInfo::Type)pSym.type(), 51537b74a387bb3993387029859c2d9d051c41c724eStephen Hines ResolveInfo::Define, 51637b74a387bb3993387029859c2d9d051c41c724eStephen Hines binding, 51737b74a387bb3993387029859c2d9d051c41c724eStephen Hines pSym.size(), // size 51837b74a387bb3993387029859c2d9d051c41c724eStephen Hines 0x0, // value 51937b74a387bb3993387029859c2d9d051c41c724eStephen Hines FragmentRef::Create(*frag, 0x0), 52037b74a387bb3993387029859c2d9d051c41c724eStephen Hines (ResolveInfo::Visibility)pSym.other()); 52187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 52287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Output all other alias symbols if any 52387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Module::AliasList* alias_list = pBuilder.getModule().getAliasList(pSym); 52437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (alias_list == NULL) 52587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *cpySym; 52687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 52787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines for (Module::alias_iterator it = alias_list->begin(), ie = alias_list->end(); 52837b74a387bb3993387029859c2d9d051c41c724eStephen Hines it != ie; 52937b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++it) { 53087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines const ResolveInfo* alias = *it; 53187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (alias == &pSym || !alias->isDyn()) 53287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines continue; 53387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 53487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 53587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines alias->name(), 53687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (ResolveInfo::Type)alias->type(), 53787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo::Define, 53887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines binding, 53987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines alias->size(), // size 54087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 0x0, // value 54187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines FragmentRef::Create(*frag, 0x0), 54287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (ResolveInfo::Visibility)alias->other()); 5435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 54487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 54587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *cpySym; 5465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 54837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::postponeRelocation(Relocation& pReloc) { 54987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.symInfo(); 55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines m_PostponedRelocs[rsym].insert(&pReloc); 5515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 55337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc) { 55487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines m_CurrentLo16Reloc = &pLo16Reloc; 55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 55687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pLo16Reloc.parent().symInfo(); 55787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 55837b74a387bb3993387029859c2d9d051c41c724eStephen Hines RelocationSet& relocs = m_PostponedRelocs[rsym]; 55987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines for (RelocationSet::iterator it = relocs.begin(); it != relocs.end(); ++it) 56087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines (*it)->apply(*this); 56187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 56287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines m_PostponedRelocs.erase(rsym); 56387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 56487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines m_CurrentLo16Reloc = NULL; 5655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 56737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isGpDisp(const Relocation& pReloc) const { 56837b74a387bb3993387029859c2d9d051c41c724eStephen Hines return strcmp("_gp_disp", pReloc.symInfo()->name()) == 0; 56987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 57137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isRel() const { 57287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return config().targets().is32Bits(); 573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines} 574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 57537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isLocalReloc(ResolveInfo& pSym) const { 57687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pSym.isUndef()) 57787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return false; 57887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 57937b74a387bb3993387029859c2d9d051c41c724eStephen Hines return pSym.isLocal() || !getTarget().isDynamicSymbol(pSym) || !pSym.isDyn(); 58087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 58187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 58237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Address MipsRelocator::getGPAddress() { 58387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return getTarget().getGOT().getGPAddr(getApplyingInput()); 58487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 58587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 586b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Address MipsRelocator::getTPOffset() { 587b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return getTarget().getTPOffset(getApplyingInput()); 588b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 589b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 590b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Address MipsRelocator::getDTPOffset() { 591b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return getTarget().getDTPOffset(getApplyingInput()); 592b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 593b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 59437b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Address MipsRelocator::getGP0() { 59587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return getTarget().getGP0(getApplyingInput()); 59687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 59787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 59887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesFragment& MipsRelocator::getLocalGOTEntry(MipsRelocationInfo& pReloc, 59937b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::DWord entryValue) { 6005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 60187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 60287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines MipsGOT& got = getTarget().getGOT(); 60387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 60487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(isLocalReloc(*rsym) && 60587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines "Attempt to get a global GOT entry for the local relocation"); 60622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 60787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Fragment* got_entry = got.lookupLocalEntry(rsym, entryValue); 60887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 60987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Found a mapping, then return the mapped entry immediately. 61037b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (got_entry != NULL) 61122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 6125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 61387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Not found. 61487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry = got.consumeLocal(); 61587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 61687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (got.isPrimaryGOTConsumed()) 617b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRel32DynEntry(*FragmentRef::Create(*got_entry, 0), NULL); 61822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 61987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got.setEntryValue(got_entry, entryValue); 62022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 62187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got.recordLocalEntry(rsym, entryValue, got_entry); 6225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 62387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *got_entry; 62487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 62587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 62637b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragment& MipsRelocator::getGlobalGOTEntry(MipsRelocationInfo& pReloc) { 62787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // rsym - The relocation target symbol 62887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 62987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines MipsGOT& got = getTarget().getGOT(); 63087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 63187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines assert(!isLocalReloc(*rsym) && 63287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines "Attempt to get a local GOT entry for the global relocation"); 63387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 63487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Fragment* got_entry = got.lookupGlobalEntry(rsym); 63587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 63687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Found a mapping, then return the mapped entry immediately. 63737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (got_entry != NULL) 63887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return *got_entry; 63987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 64087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Not found. 64187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got_entry = got.consumeGlobal(); 6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 643f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (got.isPrimaryGOTConsumed()) 644b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRel32DynEntry(*FragmentRef::Create(*got_entry, 0), rsym); 64587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 64687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got.setEntryValue(got_entry, pReloc.parent().symValue()); 64787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 64887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines got.recordGlobalEntry(rsym, got_entry); 649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 65022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return *got_entry; 6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 653b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesFragment& MipsRelocator::getTLSGOTEntry(MipsRelocationInfo& pReloc) { 654b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // rsym - The relocation target symbol 655b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 656b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsGOT& got = getTarget().getGOT(); 657b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 658b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Fragment* modEntry = got.lookupTLSEntry(rsym, pReloc.type()); 659b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 660b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // Found a mapping, then return the mapped entry immediately. 661b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (modEntry != NULL) 662b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return *modEntry; 663b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 664b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // Not found. 665b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines modEntry = got.consumeTLS(pReloc.type()); 666b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupTLSDynEntry(*modEntry, rsym, pReloc.type()); 667b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines got.recordTLSEntry(rsym, modEntry, pReloc.type()); 668b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 669b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return *modEntry; 670b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 671b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 67237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Address MipsRelocator::getGOTOffset(MipsRelocationInfo& pReloc) { 67387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 67487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines MipsGOT& got = getTarget().getGOT(); 67587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 67687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (isLocalReloc(*rsym)) { 67787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t value = pReloc.S(); 67887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 67987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (ResolveInfo::Section == rsym->type()) 68087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines value += pReloc.A(); 68187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 68287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return got.getGPRelOffset(getApplyingInput(), 68387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines getLocalGOTEntry(pReloc, value)); 68437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 68587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return got.getGPRelOffset(getApplyingInput(), getGlobalGOTEntry(pReloc)); 68687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 6875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 6885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 689b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Address MipsRelocator::getTLSGOTOffset(MipsRelocationInfo& pReloc) { 690b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsGOT& got = getTarget().getGOT(); 691b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return got.getGPRelOffset(getApplyingInput(), getTLSGOTEntry(pReloc)); 692b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 693b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 69437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::createDynRel(MipsRelocationInfo& pReloc) { 69587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocator::DWord A = pReloc.A(); 69687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocator::DWord S = pReloc.S(); 69787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 69887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 69987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 700b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (getTarget().isDynamicSymbol(*rsym)) { 701b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRel32DynEntry(pReloc.parent().targetRef(), rsym); 70287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Don't add symbol value that will be resolved by the dynamic linker. 70387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = A; 704b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else { 705b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRel32DynEntry(pReloc.parent().targetRef(), NULL); 706b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = A + S; 70787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 708b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 709b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (!isLocalReloc(*rsym) && !getTarget().symbolFinalValueIsKnown(*rsym)) 710b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines getGlobalGOTEntry(pReloc); 71187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 71287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 71337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t MipsRelocator::calcAHL(const MipsRelocationInfo& pHiReloc) { 714b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (isN64ABI()) 715b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return pHiReloc.A(); 716b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 71737b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(m_CurrentLo16Reloc != NULL && 71887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines "There is no saved R_MIPS_LO16 relocation"); 7195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 72087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t AHI = pHiReloc.A() & 0xFFFF; 72187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t ALO = m_CurrentLo16Reloc->A() & 0xFFFF; 72287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t AHL = (AHI << 16) + int16_t(ALO); 7235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return AHL; 7255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 72737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsRelocator::isN64ABI() const { 72887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return config().targets().is64Bits(); 72987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 7305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 73137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint32_t MipsRelocator::getDebugStringOffset(Relocation& pReloc) const { 73237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.type() != llvm::ELF::R_MIPS_32) 73337b74a387bb3993387029859c2d9d051c41c724eStephen Hines error(diag::unsupport_reloc_for_debug_string) 73437b74a387bb3993387029859c2d9d051c41c724eStephen Hines << getName(pReloc.type()) << "mclinker@googlegroups.com"; 73537b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (pReloc.symInfo()->type() == ResolveInfo::Section) 736fda4bbd63841e8ae3418637b24b7416f6bf56ca6Stephen McGroarty return pReloc.target() + pReloc.addend(); 73737b74a387bb3993387029859c2d9d051c41c724eStephen Hines else 73837b74a387bb3993387029859c2d9d051c41c724eStephen Hines return pReloc.symInfo()->outSymbol()->fragRef()->offset() + 73937b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() + pReloc.addend(); 74037b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 74137b74a387bb3993387029859c2d9d051c41c724eStephen Hines 74237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsRelocator::applyDebugStringOffset(Relocation& pReloc, 74337b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint32_t pOffset) { 74437b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.target() = pOffset; 74537b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 74637b74a387bb3993387029859c2d9d051c41c724eStephen Hines 747b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid MipsRelocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym, 748b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Relocation::Type pType) { 749b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Relocation& relEntry = *getTarget().getRelDyn().consumeEntry(); 750b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines relEntry.setType(pType); 751b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines relEntry.targetRef() = pFragRef; 752b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines relEntry.setSymInfo(pSym); 753b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 75437b74a387bb3993387029859c2d9d051c41c724eStephen Hines 75587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===// 75687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips32Relocator 75787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===// 75887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips32Relocator::Mips32Relocator(Mips32GNULDBackend& pParent, 75987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines const LinkerConfig& pConfig) 76037b74a387bb3993387029859c2d9d051c41c724eStephen Hines : MipsRelocator(pParent, pConfig) { 76137b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 76287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 763b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid Mips32Relocator::setupRel32DynEntry(FragmentRef& pFragRef, 764b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines ResolveInfo* pSym) { 765b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(pFragRef, pSym, llvm::ELF::R_MIPS_REL32); 766b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 767b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 768b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid Mips32Relocator::setupTLSDynEntry(Fragment& pFrag, ResolveInfo* pSym, 769b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Relocation::Type pType) { 770b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pSym = pSym->isLocal() ? nullptr : pSym; 771b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pType == llvm::ELF::R_MIPS_TLS_GD) { 772b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0); 773b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD32); 774b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines FragmentRef& relFrag = *FragmentRef::Create(*pFrag.getNextNode(), 0); 775b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(relFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPREL32); 776b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else if (pType == llvm::ELF::R_MIPS_TLS_LDM) { 777b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0); 778b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD32); 779b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else if (pType == llvm::ELF::R_MIPS_TLS_GOTTPREL) { 780b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0); 781b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_TPREL32); 782b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else { 783b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines llvm_unreachable("Unexpected relocation"); 784b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } 785b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 786b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 787b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Size Mips32Relocator::getSize(Relocation::Type pType) const { 788b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return ApplyFunctions[pType & 0xff].size; 78987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 79087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 79187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===// 79287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips64Relocator 79387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===// 79487f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips64Relocator::Mips64Relocator(Mips64GNULDBackend& pParent, 79587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines const LinkerConfig& pConfig) 79637b74a387bb3993387029859c2d9d051c41c724eStephen Hines : MipsRelocator(pParent, pConfig) { 79737b74a387bb3993387029859c2d9d051c41c724eStephen Hines} 79887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 799b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid Mips64Relocator::setupRel32DynEntry(FragmentRef& pFragRef, 800b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines ResolveInfo* pSym) { 80137b74a387bb3993387029859c2d9d051c41c724eStephen Hines Relocation::Type type = llvm::ELF::R_MIPS_REL32 | llvm::ELF::R_MIPS_64 << 8; 802b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(pFragRef, pSym, type); 803b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 80487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 805b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesvoid Mips64Relocator::setupTLSDynEntry(Fragment& pFrag, ResolveInfo* pSym, 806b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Relocation::Type pType) { 807b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pSym = pSym->isLocal() ? nullptr : pSym; 808b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pType == llvm::ELF::R_MIPS_TLS_GD) { 809b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0); 810b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD64); 811b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines FragmentRef& relFrag = *FragmentRef::Create(*pFrag.getNextNode(), 0); 812b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(relFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPREL64); 813b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else if (pType == llvm::ELF::R_MIPS_TLS_LDM) { 814b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0); 815b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_DTPMOD64); 816b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else if (pType == llvm::ELF::R_MIPS_TLS_GOTTPREL) { 817b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines FragmentRef& modFrag = *FragmentRef::Create(pFrag, 0); 818b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines setupRelDynEntry(modFrag, pSym, llvm::ELF::R_MIPS_TLS_TPREL64); 819b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else { 820b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines llvm_unreachable("Unexpected relocation"); 821b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } 822b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 823b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 824b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesRelocator::Size Mips64Relocator::getSize(Relocation::Type pType) const { 825b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (((pType >> 16) & 0xff) != llvm::ELF::R_MIPS_NONE) 826b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return ApplyFunctions[(pType >> 16) & 0xff].size; 827b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (((pType >> 8) & 0xff) != llvm::ELF::R_MIPS_NONE) 828b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return ApplyFunctions[(pType >> 8) & 0xff].size; 829b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return ApplyFunctions[pType & 0xff].size; 8305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 8335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation // 8345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 8355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type 83737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result none(MipsRelocationInfo& pReloc, 83837b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 839551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A 84337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result abs32(MipsRelocationInfo& pReloc, 84437b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 84587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 84687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 84787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocator::DWord A = pReloc.A(); 84887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocator::DWord S = pReloc.S(); 8495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& target_sect = 85137b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.parent().targetRef().frag()->getParent()->getSection(); 852affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 85337b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If the flag of target section is not ALLOC, we will not scan this 85437b74a387bb3993387029859c2d9d051c41c724eStephen Hines // relocation 855affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // but perform static relocation. (e.g., applying .debug section) 85637b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) { 85787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = S + A; 858551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 859affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 860affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 861f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (rsym->reserved() & MipsRelocator::ReserveRel) { 86287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.createDynRel(pReloc); 863551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 864affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 8655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 86687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = S + A; 86787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 868551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 86987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 87087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 87187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_26: 87287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// local : ((A | ((P + 4) & 0x3F000000)) + S) >> 2 87387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// external: (sign–extend(A) + S) >> 2 87437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result rel26(MipsRelocationInfo& pReloc, 87537b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 87687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 87787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 87837b74a387bb3993387029859c2d9d051c41c724eStephen Hines int32_t A = pParent.isN64ABI() ? pReloc.A() : (pReloc.A() & 0x03FFFFFF) << 2; 87987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t P = pReloc.P(); 88087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t S = rsym->reserved() & MipsRelocator::ReservePLT 881b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines ? helper_get_PLT_address(*rsym, pParent) 88287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines : pReloc.S(); 88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 88487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->isLocal()) 88587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = A | ((P + 4) & 0x3F000000); 88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 88737b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.result() = signExtend<28>(A); 88887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 88987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = (pReloc.result() + S) >> 2; 8905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 891551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 8925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16: 8955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: ((AHL + S) - (short)(AHL + S)) >> 16 8965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 89737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result hi16(MipsRelocationInfo& pReloc, 89837b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 89987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t AHL = pParent.calcAHL(pReloc); 9005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 90187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pParent.isGpDisp(pReloc.parent())) { 90287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t P = pReloc.P(); 90387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t GP = pParent.getGPAddress(); 90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16; 90537b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 90687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t S = pReloc.S(); 90787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pParent.isN64ABI()) 90887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = (pReloc.A() + S + 0x8000ull) >> 16; 90987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 91087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = ((AHL + S) - (int16_t)(AHL + S)) >> 16; 9115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 9125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 913551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16: 9175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: AHL + S 9185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : AHL + GP - P + 4 91937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result lo16(MipsRelocationInfo& pReloc, 92037b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 92187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // AHL is a combination of HI16 and LO16 addends. But R_MIPS_LO16 92287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // uses low 16 bits of the AHL. That is why we do not need R_MIPS_HI16 92387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // addend here. 92487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t AHL = (pReloc.A() & 0xFFFF); 92587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 92687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pParent.isGpDisp(pReloc.parent())) { 92787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t P = pReloc.P(); 92887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t GP = pParent.getGPAddress(); 92987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = AHL + GP - P + 4; 93037b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 93187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t S = pReloc.S(); 93287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = AHL + S; 9335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 9345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.applyPostponedRelocations(pReloc); 93687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 937551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 93887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 93987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 94087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GPREL16: 94187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// external: sign–extend(A) + S - GP 94287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// local : sign–extend(A) + S + GP0 – GP 94337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gprel16(MipsRelocationInfo& pReloc, 94437b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 94587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // Remember to add the section offset to A. 94687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t A = pReloc.A(); 94787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t S = pReloc.S(); 94887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t GP0 = pParent.getGP0(); 94987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t GP = pParent.getGPAddress(); 95087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 95187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 95287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->isLocal()) 95387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = A + S + GP0 - GP; 95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines else 95587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = A + S - GP; 9565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 957551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 9585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 9595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 9605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16: 9615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local : G (calculate AHL and put high 16 bit to GOT) 9625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// external: G 96337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result got16(MipsRelocationInfo& pReloc, 96437b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 96587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pReloc.parent().symInfo()->isLocal()) { 96687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t AHL = pParent.calcAHL(pReloc); 96787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t S = pReloc.S(); 96887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t res = (AHL + S + 0x8000) & 0xFFFF0000; 9695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 97087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines MipsGOT& got = pParent.getTarget().getGOT(); 9715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 97287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Fragment& got_entry = pParent.getLocalGOTEntry(pReloc, res); 973affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 97487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = got.getGPRelOffset(pParent.getApplyingInput(), got_entry); 97537b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 97687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = pParent.getGOTOffset(pReloc); 9775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 9785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 979551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 980d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 981d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 982d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTHI16: 983d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// external: (G - (short)G) >> 16 + A 98437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gothi16(MipsRelocationInfo& pReloc, 98537b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 98687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocator::Address G = pParent.getGOTOffset(pReloc); 98787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t A = pReloc.A(); 988d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 98987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = (G - (int16_t)G) >> (16 + A); 990d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 991551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 992d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao} 993d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 994d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// R_MIPS_GOTLO16: 995d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// external: G & 0xffff 99637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gotlo16(MipsRelocationInfo& pReloc, 99737b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 99887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = pParent.getGOTOffset(pReloc) & 0xffff; 999d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 1000551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 100187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 100287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 100387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_SUB: 100487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// external/local: S - A 100537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result sub(MipsRelocationInfo& pReloc, 100637b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 100787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t S = pReloc.S(); 100887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t A = pReloc.A(); 100987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 101087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = S - A; 1011d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 1012551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 10135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 10145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G 101637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result call16(MipsRelocationInfo& pReloc, 101737b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 101887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = pParent.getGOTOffset(pReloc); 10195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1020551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 10215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 10225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP 102437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gprel32(MipsRelocationInfo& pReloc, 102537b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 1026affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Remember to add the section offset to A. 102787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t A = pReloc.A(); 102887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t S = pReloc.S(); 102987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t GP0 = pParent.getGP0(); 103087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint64_t GP = pParent.getGPAddress(); 103187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 103287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = A + S + GP0 - GP; 103387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1034551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 103587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 103687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 103787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_64: S + A 103837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result abs64(MipsRelocationInfo& pReloc, 103937b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 104087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // FIXME (simon): Consider to merge with abs32() or use the same function 104187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // but with another mask size. 104287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines ResolveInfo* rsym = pReloc.parent().symInfo(); 104387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 104487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocator::DWord A = pReloc.A(); 104587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Relocator::DWord S = pReloc.S(); 104687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 104787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& target_sect = 104837b74a387bb3993387029859c2d9d051c41c724eStephen Hines pReloc.parent().targetRef().frag()->getParent()->getSection(); 104987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 105037b74a387bb3993387029859c2d9d051c41c724eStephen Hines // If the flag of target section is not ALLOC, we will not scan this 105137b74a387bb3993387029859c2d9d051c41c724eStephen Hines // relocation 105287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // but perform static relocation. (e.g., applying .debug section) 105387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 105487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = S + A; 1055551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 105687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 105787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 105887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (rsym->reserved() & MipsRelocator::ReserveRel) { 105987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pParent.createDynRel(pReloc); 1060551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 106187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 10625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 106387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = S + A; 10645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1065551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 10665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1067d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 106887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GOT_DISP / R_MIPS_GOT_PAGE: G 106937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gotdisp(MipsRelocationInfo& pReloc, 107037b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 107187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pReloc.result() = pParent.getGOTOffset(pReloc); 107287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1073551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 107487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 107587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 107687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_GOT_OFST: 107737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result gotoff(MipsRelocationInfo& pReloc, 107837b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 107987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines // FIXME (simon): Needs to be implemented. 1080551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 108187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 108287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 108387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_MIPS_JALR: 108437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result jalr(MipsRelocationInfo& pReloc, 108537b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 1086551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 108787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 108887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1089b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC16 1090b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc16(MipsRelocationInfo& pReloc, 1091b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1092b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t A = signExtend<18>(pReloc.A() << 2); 1093b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t S = pReloc.S(); 1094b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t P = pReloc.P(); 1095b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = (A + S - P) >> 2; 1096b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return Relocator::OK; 1097b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 1098b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 1099b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC32 1100b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc32(MipsRelocationInfo& pReloc, 1101b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1102b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t A = pReloc.A(); 1103b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t S = pReloc.S(); 1104b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t P = pReloc.P(); 1105b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = A + S - P; 1106b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return Relocator::OK; 1107b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 1108b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 1109b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC18_S3 1110b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc18_s3(MipsRelocationInfo& pReloc, 1111b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1112b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t A = signExtend<21>(pReloc.A() << 3); 1113b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t S = pReloc.S(); 1114b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t P = pReloc.P(); 1115b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = (S + A - ((P | 7) ^ 7)) >> 3; 1116b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return Relocator::OK; 1117b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 1118b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 1119b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC19_S2 1120b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc19_s2(MipsRelocationInfo& pReloc, 1121b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1122b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t A = signExtend<21>(pReloc.A() << 2); 1123b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t S = pReloc.S(); 1124b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t P = pReloc.P(); 1125b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = (A + S - P) >> 2; 1126b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return Relocator::OK; 1127b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 1128b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 1129b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC21_S2 1130b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc21_s2(MipsRelocationInfo& pReloc, 113137b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 1132b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int32_t A = signExtend<23>(pReloc.A() << 2); 113387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines int32_t S = pReloc.S(); 1134b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int32_t P = pReloc.P(); 1135b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = (A + S - P) >> 2; 1136b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return Relocator::OK; 1137b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 1138b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 1139b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PC26_S2 1140b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pc26_s2(MipsRelocationInfo& pReloc, 1141b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1142b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t A = signExtend<28>(pReloc.A() << 2); 1143b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t S = pReloc.S(); 1144b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t P = pReloc.P(); 1145b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = (A + S - P) >> 2; 1146b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return Relocator::OK; 1147b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 114887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1149b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PCHI16 1150b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pchi16(MipsRelocationInfo& pReloc, 1151b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1152b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines uint64_t AHL = pParent.calcAHL(pReloc); 1153b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t S = pReloc.S(); 1154b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t P = pReloc.P(); 1155b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = (S + AHL - P + 0x8000) >> 16; 1156b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return Relocator::OK; 1157b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 115887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1159b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_PCLO16 1160b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result pclo16(MipsRelocationInfo& pReloc, 1161b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1162b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int32_t AHL = pReloc.A() & 0xFFFF; 1163b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t S = pReloc.S(); 1164b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines int64_t P = pReloc.P(); 1165b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = S + AHL - P; 1166b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pParent.applyPostponedRelocations(pReloc); 1167551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 116887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 116987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1170b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_DTPREL_HI16 1171b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// local/external: (A + S - TP Offset) >> 16 1172b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// _gp_disp : (A + GP - P - TP Offset) >> 16 1173b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result tlshi16(MipsRelocationInfo& pReloc, 1174b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1175b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines uint64_t A = pReloc.A() & 0xFFFF; 1176b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pReloc.type() == llvm::ELF::R_MIPS_TLS_TPREL_HI16) 1177b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines A -= pParent.getTPOffset(); 1178b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines else if (pReloc.type() == llvm::ELF::R_MIPS_TLS_DTPREL_HI16) 1179b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines A -= pParent.getDTPOffset(); 1180b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines else 1181b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines llvm_unreachable("Unexpected relocation"); 118287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1183b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pParent.isGpDisp(pReloc.parent())) 1184b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = (A + pReloc.S() - pReloc.P() + 0x8000) >> 16; 1185b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines else 1186b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = (A + pReloc.S() + 0x8000) >> 16; 118787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1188551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 118987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 119087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1191b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_DTPREL_LO16 1192b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// local/external: A + S - TP Offset 1193b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// _gp_disp : A + GP - P + 4 - TP Offset 1194b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result tlslo16(MipsRelocationInfo& pReloc, 119537b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 1196b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines uint64_t A = pReloc.A() & 0xFFFF; 1197b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pReloc.type() == llvm::ELF::R_MIPS_TLS_TPREL_LO16) 1198b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines A -= pParent.getTPOffset(); 1199b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines else if (pReloc.type() == llvm::ELF::R_MIPS_TLS_DTPREL_LO16) 1200b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines A -= pParent.getDTPOffset(); 1201b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines else 1202b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines llvm_unreachable("Unexpected relocation"); 1203b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 1204b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (pParent.isGpDisp(pReloc.parent())) 1205b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = A + pReloc.S() - pReloc.P() + 4; 1206b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines else 1207b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = A + pReloc.S(); 120887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 121087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 121187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 1212b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines// R_MIPS_TLS_GD, R_MIPS_TLS_LDM 1213b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesstatic MipsRelocator::Result tlsgot(MipsRelocationInfo& pReloc, 1214b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines MipsRelocator& pParent) { 1215b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pReloc.result() = pParent.getTLSGOTOffset(pReloc); 1216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines return Relocator::OK; 121787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 121887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 121937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic MipsRelocator::Result unsupported(MipsRelocationInfo& pReloc, 122037b74a387bb3993387029859c2d9d051c41c724eStephen Hines MipsRelocator& pParent) { 122137b74a387bb3993387029859c2d9d051c41c724eStephen Hines return Relocator::Unsupported; 122287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} 122337b74a387bb3993387029859c2d9d051c41c724eStephen Hines 122437b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 1225