MipsRelocator.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- MipsRelocationFactory.cpp -----------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h> 125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ErrorHandling.h> 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Layout.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/OutputRelocSection.h> 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFactory.h" 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "MipsRelocationFunctions.h" 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_MIPS_APPLY_RELOC_FUNCS 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//========================== 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// MipsRelocationFactory 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::MipsRelocationFactory(size_t pNum, 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& pParent) 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao : RelocationFactory(pNum), 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_Target(pParent), 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_AHL(0) 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsRelocationFactory::applyRelocation(Relocation& pRelocation, 345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo) 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// the prototype of applying function 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao typedef Result (*ApplyFunctionType)(Relocation&, 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory&); 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // the table entry of applying functions 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao struct ApplyFunctionTriple { 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ApplyFunctionType func; 455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao unsigned int type; 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const char* name; 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao }; 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // declare the table of applying functions 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao static ApplyFunctionTriple apply_functions[] = { 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao DECL_MIPS_APPLY_RELOC_FUNC_PTRS 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao }; 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation::Type type = pRelocation.type(); 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (type >= sizeof(apply_functions) / sizeof(apply_functions[0])) { 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::report_fatal_error(llvm::Twine("Unknown relocation type. " 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "To symbol `") + 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pRelocation.symInfo()->name() + 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine("'.")); 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // apply the relocation 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Result result = apply_functions[type].func(pRelocation, pLDInfo, *this); 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // check result 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (Overflow == result) { 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::report_fatal_error(llvm::Twine("Applying relocation `") + 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(apply_functions[type].name) + 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine("' causes overflow. on symbol: `") + 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(pRelocation.symInfo()->name()) + 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine("'.")); 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (BadReloc == result) { 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::report_fatal_error(llvm::Twine("Applying relocation `") + 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(apply_functions[type].name) + 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine("' encounters unexpected opcode. " 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "on symbol: `") + 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine(pRelocation.symInfo()->name()) + 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::Twine("'.")); 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation helper function // 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic const char * const GP_DISP_NAME = "_gp_disp"; 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Get an relocation entry in .rel.dyn and set its type to R_MIPS_REL32, 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// its FragmentRef to pReloc->targetFrag() and its ResolveInfo 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// to pReloc->symInfo() 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_SetRelDynEntry(Relocation& pReloc, 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelDyn().getEntry(*rsym, false, exist); 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_MIPS_REL32); 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(0); 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Find next R_MIPS_LO16 relocation paired to pReloc. 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation* helper_FindLo16Reloc(Relocation& pReloc) 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode()); 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao while (NULL != reloc) 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao { 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (llvm::ELF::R_MIPS_LO16 == reloc->type() && 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc->symInfo() == pReloc.symInfo()) 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return reloc; 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao reloc = static_cast<Relocation*>(reloc->getNextNode()); 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check the symbol is _gp_disp. 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool helper_isGpDisp(const Relocation& pReloc) 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const ResolveInfo* rsym = pReloc.symInfo(); 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0 == strcmp(GP_DISP_NAME, rsym->name()); 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent) 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pParent.getTarget().getGOT().getSection().addr() + 0x7FF0; 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoGOTEntry& helper_GetGOTEntry(Relocation& pReloc, 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist); 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (exist) 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return got_entry; 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If we first get this GOT entry, we should initialize it. 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveGot) { 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(pReloc.symValue()); 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!"); 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return got_entry; 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc, 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent); 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0; 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoint32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc) 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 || 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) && 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pLoReloc.type() == llvm::ELF::R_MIPS_LO16 && 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "Incorrect type of relocation for AHL calculation"); 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Note the addend is section symbol offset here 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert (pHiReloc.addend() == pLoReloc.addend()); 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHI = pHiReloc.target(); 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t ALO = pLoReloc.target(); 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + pLoReloc.addend(); 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return AHL; 1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc, 1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsGNULDBackend& ld_backend = pParent.getTarget(); 1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool exist; 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation& rel_entry = 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao *ld_backend.getRelDyn().getEntry(*rsym, false, exist); 2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setType(llvm::ELF::R_MIPS_REL32); 2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.targetRef() = pReloc.targetRef(); 2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rel_entry.setSymInfo(rsym->isLocal() ? NULL : rsym); 2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation functions implementation // 2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================// 2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_NONE and those unsupported/deprecated relocation type 2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result none(Relocation& pReloc, 2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_32: S + A 2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result abs32(Relocation& pReloc, 2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->reserved() & MipsGNULDBackend::ReserveRel) { 2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao helper_DynRel(pReloc, pParent); 2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::DWord S = pReloc.symValue(); 2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (S + A); 2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_HI16: 2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: ((AHL + S) - (short)(AHL + S)) >> 16 2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result hi16(Relocation& pReloc, 2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16"); 2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t P = pReloc.place(pParent.getLayout()); 2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16; 2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = ((AHL + S) - (int16_t)(AHL + S)) >> 16; 2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_LO16: 2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local/external: AHL + S 2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// _gp_disp : AHL + GP - P + 4 2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result lo16(Relocation& pReloc, 2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = pParent.getAHL(); 2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = 0; 2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (helper_isGpDisp(pReloc)) { 2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t P = pReloc.place(pParent.getLayout()); 2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = AHL + GP - P + 4; 2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao res = AHL + S; 2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (res & 0xFFFF); 2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GOT16: 3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// local : G (calculate AHL and put high 16 bit to GOT) 3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// external: G 3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result got16(Relocation& pReloc, 3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (rsym->isLocal()) { 3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao Relocation* lo_reloc = helper_FindLo16Reloc(pReloc); 3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16"); 3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc); 3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pParent.setAHL(AHL); 3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent); 3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t res = (AHL + S + 0x8000) & 0xFFFF0000; 3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao got_entry.setContent(res); 3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent); 3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_CALL16: G 3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result call16(Relocation& pReloc, 3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent); 3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() &= 0xFFFF0000; 3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() |= (G & 0xFFFF); 3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_MIPS_GPREL32: A + S + GP0 - GP 3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic 3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsRelocationFactory::Result gprel32(Relocation& pReloc, 3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const MCLDInfo& pLDInfo, 3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MipsRelocationFactory& pParent) 3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t A = pReloc.target(); 3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t S = pReloc.symValue(); 3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao int32_t GP = helper_GetGP(pParent); 3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // llvm does not emits SHT_MIPS_REGINFO section. 3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Assume that GP0 is zero. 3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao pReloc.target() = (A + S - GP) & 0xFFFFFFFF; 3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return MipsRelocationFactory::OK; 3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 364