MipsRelocator.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
1//===- MipsRelocator.cpp -----------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include "MipsRelocator.h" 10#include "MipsRelocationFunctions.h" 11 12#include <mcld/IRBuilder.h> 13#include <mcld/LinkerConfig.h> 14#include <mcld/Object/ObjectBuilder.h> 15#include <mcld/Support/MsgHandling.h> 16#include <mcld/Target/OutputRelocSection.h> 17#include <mcld/LD/ELFFileFormat.h> 18 19#include <llvm/ADT/Twine.h> 20#include <llvm/Support/ELF.h> 21 22namespace llvm { 23namespace ELF { 24 25// FIXME: Consider upstream these relocation types to LLVM. 26enum { 27 R_MIPS_LA25_LUI = 200, 28 R_MIPS_LA25_J = 201, 29 R_MIPS_LA25_ADD = 202, 30 R_MIPS_PC32 = 248, 31}; 32 33} // end namespace ELF 34} // end namespace llvm 35 36using namespace mcld; 37 38//===----------------------------------------------------------------------===// 39// MipsRelocationInfo 40//===----------------------------------------------------------------------===// 41class mcld::MipsRelocationInfo 42{ 43public: 44 static bool HasSubType(const Relocation& pParent, Relocation::Type pType) 45 { 46 if (llvm::ELF::R_MIPS_NONE == pType) 47 return true; 48 49 for (Relocation::Type type = pParent.type(); 50 llvm::ELF::R_MIPS_NONE != (type & 0xff); type >>= 8) { 51 if ((type & 0xff) == pType) 52 return true; 53 } 54 55 return false; 56 } 57 58 MipsRelocationInfo(Relocation& pParent, bool pIsRel) 59 : m_Parent(&pParent), 60 m_Type(pParent.type()), 61 m_Addend(0), 62 m_Symbol(pParent.symValue()), 63 m_Result(pParent.target()) 64 { 65 if (pIsRel && (type() < llvm::ELF::R_MIPS_LA25_LUI || 66 type() > llvm::ELF::R_MIPS_LA25_ADD)) 67 m_Addend = pParent.target(); 68 else 69 m_Addend = pParent.addend(); 70 } 71 72 bool isNone() const 73 { 74 return llvm::ELF::R_MIPS_NONE == type(); 75 } 76 77 bool isLast() const 78 { 79 return llvm::ELF::R_MIPS_NONE == (m_Type >> 8); 80 } 81 82 MipsRelocationInfo next() const 83 { 84 return MipsRelocationInfo(*m_Parent, m_Type >> 8, result(), result(), 0); 85 } 86 87 const Relocation& parent() const 88 { 89 return *m_Parent; 90 } 91 92 Relocation& parent() 93 { 94 return *m_Parent; 95 } 96 97 Relocation::Type type() const 98 { 99 return m_Type & 0xff; 100 } 101 102 Relocation::DWord A() const 103 { 104 return m_Addend; 105 } 106 107 Relocation::DWord S() const 108 { 109 return m_Symbol; 110 } 111 112 Relocation::DWord P() const 113 { 114 return parent().place(); 115 } 116 117 Relocation::DWord result() const 118 { 119 return m_Result; 120 } 121 122 Relocation::DWord& result() 123 { 124 return m_Result; 125 } 126 127private: 128 Relocation* m_Parent; 129 Relocation::Type m_Type; 130 Relocation::DWord m_Addend; 131 Relocation::DWord m_Symbol; 132 Relocation::DWord m_Result; 133 134 MipsRelocationInfo(Relocation& pParent, Relocation::Type pType, 135 Relocation::DWord pResult, 136 Relocation::DWord pAddend, Relocation::DWord pSymbol) 137 : m_Parent(&pParent), 138 m_Type(pType), 139 m_Addend(pAddend), 140 m_Symbol(pSymbol), 141 m_Result(pResult) 142 {} 143 144 bool isFirst() const { 145 return m_Type == parent().type(); 146 } 147}; 148 149//===----------------------------------------------------------------------===// 150// Relocation Functions and Tables 151//===----------------------------------------------------------------------===// 152DECL_MIPS_APPLY_RELOC_FUNCS 153 154/// the prototype of applying function 155typedef Relocator::Result (*ApplyFunctionType)(MipsRelocationInfo&, 156 MipsRelocator& pParent); 157 158 159// the table entry of applying functions 160struct ApplyFunctionTriple 161{ 162 ApplyFunctionType func; 163 unsigned int type; 164 const char* name; 165 unsigned int size; 166}; 167 168// declare the table of applying functions 169static const ApplyFunctionTriple ApplyFunctions[] = { 170 DECL_MIPS_APPLY_RELOC_FUNC_PTRS 171}; 172 173//===----------------------------------------------------------------------===// 174// MipsRelocator 175//===----------------------------------------------------------------------===// 176MipsRelocator::MipsRelocator(MipsGNULDBackend& pParent, 177 const LinkerConfig& pConfig) 178 : Relocator(pConfig), 179 m_Target(pParent), 180 m_pApplyingInput(NULL), 181 m_CurrentLo16Reloc(NULL) 182{ 183} 184 185Relocator::Result 186MipsRelocator::applyRelocation(Relocation& pReloc) 187{ 188 // If m_CurrentLo16Reloc is not NULL we are processing 189 // postponed relocation. Otherwise check relocation type 190 // and postpone it for later handling. 191 if (NULL == m_CurrentLo16Reloc && isPostponed(pReloc)) { 192 postponeRelocation(pReloc); 193 return OK; 194 } 195 196 for (MipsRelocationInfo info(pReloc, isRel()); 197 !info.isNone(); info = info.next()) { 198 if (info.type() >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) 199 return Unknown; 200 201 const ApplyFunctionTriple & triple = ApplyFunctions[info.type()]; 202 203 Result res = triple.func(info, *this); 204 if (OK != res) 205 return res; 206 207 if (info.isLast()) { 208 uint64_t mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - triple.size); 209 pReloc.target() &= ~mask; 210 pReloc.target() |= info.result() & mask; 211 } 212 } 213 214 return OK; 215} 216 217const char* MipsRelocator::getName(Relocation::Type pType) const 218{ 219 return ApplyFunctions[pType & 0xff].name; 220} 221 222Relocator::Size MipsRelocator::getSize(Relocation::Type pType) const 223{ 224 return ApplyFunctions[pType & 0xff].size; 225} 226 227void MipsRelocator::scanRelocation(Relocation& pReloc, 228 IRBuilder& pBuilder, 229 Module& pModule, 230 LDSection& pSection, 231 Input& pInput) 232{ 233 // rsym - The relocation target symbol 234 ResolveInfo* rsym = pReloc.symInfo(); 235 assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation"); 236 237 // Skip relocation against _gp_disp 238 if (NULL != getTarget().getGpDispSymbol() && 239 rsym == getTarget().getGpDispSymbol()->resolveInfo()) 240 return; 241 242 assert(NULL != pSection.getLink()); 243 if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 244 return; 245 246 for (MipsRelocationInfo info(pReloc, isRel()); 247 !info.isNone(); info = info.next()) { 248 // We test isLocal or if pInputSym is not a dynamic symbol 249 // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn() 250 // Don't put undef symbols into local entries. 251 if (isLocalReloc(*rsym)) 252 scanLocalReloc(info, pBuilder, pSection); 253 else 254 scanGlobalReloc(info, pBuilder, pSection); 255 256 if (getTarget().needsLA25Stub(info.type(), info.parent().symInfo())) 257 getTarget().addNonPICBranchSym(pReloc.symInfo()); 258 } 259 260 // Check if we should issue undefined reference 261 // for the relocation target symbol. 262 if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 263 issueUndefRef(pReloc, pSection, pInput); 264} 265 266bool MipsRelocator::initializeScan(Input& pInput) 267{ 268 if (LinkerConfig::Object != config().codeGenType()) 269 getTarget().getGOT().initializeScan(pInput); 270 return true; 271} 272 273bool MipsRelocator::finalizeScan(Input& pInput) 274{ 275 if (LinkerConfig::Object != config().codeGenType()) 276 getTarget().getGOT().finalizeScan(pInput); 277 return true; 278} 279 280bool MipsRelocator::initializeApply(Input& pInput) 281{ 282 m_pApplyingInput = &pInput; 283 return true; 284} 285 286bool MipsRelocator::finalizeApply(Input& pInput) 287{ 288 m_pApplyingInput = NULL; 289 return true; 290} 291 292void MipsRelocator::scanLocalReloc(MipsRelocationInfo& pReloc, 293 IRBuilder& pBuilder, 294 const LDSection& pSection) 295{ 296 ResolveInfo* rsym = pReloc.parent().symInfo(); 297 298 switch (pReloc.type()){ 299 case llvm::ELF::R_MIPS_NONE: 300 case llvm::ELF::R_MIPS_16: 301 break; 302 case llvm::ELF::R_MIPS_32: 303 case llvm::ELF::R_MIPS_64: 304 if (LinkerConfig::DynObj == config().codeGenType()) { 305 // TODO: (simon) The gold linker does not create an entry in .rel.dyn 306 // section if the symbol section flags contains SHF_EXECINSTR. 307 // 1. Find the reason of this condition. 308 // 2. Check this condition here. 309 getTarget().getRelDyn().reserveEntry(); 310 rsym->setReserved(rsym->reserved() | ReserveRel); 311 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 312 } 313 break; 314 case llvm::ELF::R_MIPS_REL32: 315 case llvm::ELF::R_MIPS_26: 316 case llvm::ELF::R_MIPS_HI16: 317 case llvm::ELF::R_MIPS_LO16: 318 case llvm::ELF::R_MIPS_PC16: 319 case llvm::ELF::R_MIPS_SHIFT5: 320 case llvm::ELF::R_MIPS_SHIFT6: 321 case llvm::ELF::R_MIPS_SUB: 322 case llvm::ELF::R_MIPS_INSERT_A: 323 case llvm::ELF::R_MIPS_INSERT_B: 324 case llvm::ELF::R_MIPS_DELETE: 325 case llvm::ELF::R_MIPS_HIGHER: 326 case llvm::ELF::R_MIPS_HIGHEST: 327 case llvm::ELF::R_MIPS_SCN_DISP: 328 case llvm::ELF::R_MIPS_REL16: 329 case llvm::ELF::R_MIPS_ADD_IMMEDIATE: 330 case llvm::ELF::R_MIPS_PJUMP: 331 case llvm::ELF::R_MIPS_RELGOT: 332 case llvm::ELF::R_MIPS_JALR: 333 case llvm::ELF::R_MIPS_GLOB_DAT: 334 case llvm::ELF::R_MIPS_COPY: 335 case llvm::ELF::R_MIPS_JUMP_SLOT: 336 break; 337 case llvm::ELF::R_MIPS_GOT16: 338 case llvm::ELF::R_MIPS_CALL16: 339 case llvm::ELF::R_MIPS_GOT_HI16: 340 case llvm::ELF::R_MIPS_CALL_HI16: 341 case llvm::ELF::R_MIPS_GOT_LO16: 342 case llvm::ELF::R_MIPS_CALL_LO16: 343 case llvm::ELF::R_MIPS_GOT_DISP: 344 case llvm::ELF::R_MIPS_GOT_PAGE: 345 case llvm::ELF::R_MIPS_GOT_OFST: 346 if (getTarget().getGOT().reserveLocalEntry(*rsym, 347 pReloc.type(), pReloc.A())) { 348 if (getTarget().getGOT().hasMultipleGOT()) 349 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 350 } 351 break; 352 case llvm::ELF::R_MIPS_GPREL32: 353 case llvm::ELF::R_MIPS_GPREL16: 354 case llvm::ELF::R_MIPS_LITERAL: 355 break; 356 case llvm::ELF::R_MIPS_TLS_DTPMOD32: 357 case llvm::ELF::R_MIPS_TLS_DTPREL32: 358 case llvm::ELF::R_MIPS_TLS_DTPMOD64: 359 case llvm::ELF::R_MIPS_TLS_DTPREL64: 360 case llvm::ELF::R_MIPS_TLS_GD: 361 case llvm::ELF::R_MIPS_TLS_LDM: 362 case llvm::ELF::R_MIPS_TLS_DTPREL_HI16: 363 case llvm::ELF::R_MIPS_TLS_DTPREL_LO16: 364 case llvm::ELF::R_MIPS_TLS_GOTTPREL: 365 case llvm::ELF::R_MIPS_TLS_TPREL32: 366 case llvm::ELF::R_MIPS_TLS_TPREL64: 367 case llvm::ELF::R_MIPS_TLS_TPREL_HI16: 368 case llvm::ELF::R_MIPS_TLS_TPREL_LO16: 369 break; 370 case llvm::ELF::R_MIPS_PC32: 371 break; 372 default: 373 fatal(diag::unknown_relocation) << (int)pReloc.type() << rsym->name(); 374 } 375} 376 377void MipsRelocator::scanGlobalReloc(MipsRelocationInfo& pReloc, 378 IRBuilder& pBuilder, 379 const LDSection& pSection) 380{ 381 ResolveInfo* rsym = pReloc.parent().symInfo(); 382 383 switch (pReloc.type()){ 384 case llvm::ELF::R_MIPS_NONE: 385 case llvm::ELF::R_MIPS_INSERT_A: 386 case llvm::ELF::R_MIPS_INSERT_B: 387 case llvm::ELF::R_MIPS_DELETE: 388 case llvm::ELF::R_MIPS_TLS_DTPMOD64: 389 case llvm::ELF::R_MIPS_TLS_DTPREL64: 390 case llvm::ELF::R_MIPS_REL16: 391 case llvm::ELF::R_MIPS_ADD_IMMEDIATE: 392 case llvm::ELF::R_MIPS_PJUMP: 393 case llvm::ELF::R_MIPS_RELGOT: 394 case llvm::ELF::R_MIPS_TLS_TPREL64: 395 break; 396 case llvm::ELF::R_MIPS_32: 397 case llvm::ELF::R_MIPS_64: 398 case llvm::ELF::R_MIPS_HI16: 399 case llvm::ELF::R_MIPS_LO16: 400 if (getTarget().symbolNeedsDynRel(*rsym, false, true)) { 401 getTarget().getRelDyn().reserveEntry(); 402 if (getTarget().symbolNeedsCopyReloc(pReloc.parent(), *rsym)) { 403 LDSymbol& cpySym = defineSymbolforCopyReloc(pBuilder, *rsym); 404 addCopyReloc(*cpySym.resolveInfo()); 405 } 406 else { 407 // set Rel bit 408 rsym->setReserved(rsym->reserved() | ReserveRel); 409 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 410 } 411 } 412 break; 413 case llvm::ELF::R_MIPS_GOT16: 414 case llvm::ELF::R_MIPS_CALL16: 415 case llvm::ELF::R_MIPS_GOT_DISP: 416 case llvm::ELF::R_MIPS_GOT_HI16: 417 case llvm::ELF::R_MIPS_CALL_HI16: 418 case llvm::ELF::R_MIPS_GOT_LO16: 419 case llvm::ELF::R_MIPS_CALL_LO16: 420 case llvm::ELF::R_MIPS_GOT_PAGE: 421 case llvm::ELF::R_MIPS_GOT_OFST: 422 if (getTarget().getGOT().reserveGlobalEntry(*rsym)) { 423 if (getTarget().getGOT().hasMultipleGOT()) 424 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 425 } 426 break; 427 case llvm::ELF::R_MIPS_LITERAL: 428 case llvm::ELF::R_MIPS_GPREL32: 429 fatal(diag::invalid_global_relocation) << (int)pReloc.type() 430 << rsym->name(); 431 break; 432 case llvm::ELF::R_MIPS_GPREL16: 433 break; 434 case llvm::ELF::R_MIPS_26: 435 // Create a PLT entry if the symbol requires it and does not have it. 436 if (getTarget().symbolNeedsPLT(*rsym) && 437 !(rsym->reserved() & ReservePLT)) { 438 getTarget().getPLT().reserveEntry(); 439 getTarget().getGOTPLT().reserve(); 440 getTarget().getRelPLT().reserveEntry(); 441 rsym->setReserved(rsym->reserved() | ReservePLT); 442 } 443 break; 444 case llvm::ELF::R_MIPS_PC16: 445 break; 446 case llvm::ELF::R_MIPS_16: 447 case llvm::ELF::R_MIPS_SHIFT5: 448 case llvm::ELF::R_MIPS_SHIFT6: 449 case llvm::ELF::R_MIPS_SUB: 450 case llvm::ELF::R_MIPS_HIGHER: 451 case llvm::ELF::R_MIPS_HIGHEST: 452 case llvm::ELF::R_MIPS_SCN_DISP: 453 break; 454 case llvm::ELF::R_MIPS_TLS_DTPREL32: 455 case llvm::ELF::R_MIPS_TLS_GD: 456 case llvm::ELF::R_MIPS_TLS_LDM: 457 case llvm::ELF::R_MIPS_TLS_DTPREL_HI16: 458 case llvm::ELF::R_MIPS_TLS_DTPREL_LO16: 459 case llvm::ELF::R_MIPS_TLS_GOTTPREL: 460 case llvm::ELF::R_MIPS_TLS_TPREL32: 461 case llvm::ELF::R_MIPS_TLS_TPREL_HI16: 462 case llvm::ELF::R_MIPS_TLS_TPREL_LO16: 463 break; 464 case llvm::ELF::R_MIPS_REL32: 465 case llvm::ELF::R_MIPS_JALR: 466 case llvm::ELF::R_MIPS_PC32: 467 break; 468 case llvm::ELF::R_MIPS_COPY: 469 case llvm::ELF::R_MIPS_GLOB_DAT: 470 case llvm::ELF::R_MIPS_JUMP_SLOT: 471 fatal(diag::dynamic_relocation) << (int)pReloc.type(); 472 break; 473 default: 474 fatal(diag::unknown_relocation) << (int)pReloc.type() << rsym->name(); 475 } 476} 477 478bool MipsRelocator::isPostponed(const Relocation& pReloc) const 479{ 480 if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_HI16)) 481 return true; 482 483 if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_GOT16) && 484 pReloc.symInfo()->isLocal()) 485 return true; 486 487 return false; 488} 489 490void MipsRelocator::addCopyReloc(ResolveInfo& pSym) 491{ 492 Relocation& relEntry = *getTarget().getRelDyn().consumeEntry(); 493 relEntry.setType(llvm::ELF::R_MIPS_COPY); 494 assert(pSym.outSymbol()->hasFragRef()); 495 relEntry.targetRef().assign(*pSym.outSymbol()->fragRef()); 496 relEntry.setSymInfo(&pSym); 497} 498 499LDSymbol& MipsRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 500 const ResolveInfo& pSym) 501{ 502 // Get or create corresponding BSS LDSection 503 ELFFileFormat* fileFormat = getTarget().getOutputFormat(); 504 LDSection* bssSectHdr = 505 ResolveInfo::ThreadLocal == pSym.type() ? &fileFormat->getTBSS() 506 : &fileFormat->getBSS(); 507 508 // Get or create corresponding BSS SectionData 509 SectionData* bssData = 510 bssSectHdr->hasSectionData() ? bssSectHdr->getSectionData() 511 : IRBuilder::CreateSectionData(*bssSectHdr); 512 513 // Determine the alignment by the symbol value 514 // FIXME: here we use the largest alignment 515 uint32_t addrAlign = config().targets().bitclass() / 8; 516 517 // Allocate space in BSS for the copy symbol 518 Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 519 uint64_t size = ObjectBuilder::AppendFragment(*frag, *bssData, addrAlign); 520 bssSectHdr->setSize(bssSectHdr->size() + size); 521 522 // Change symbol binding to Global if it's a weak symbol 523 ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 524 if (binding == ResolveInfo::Weak) 525 binding = ResolveInfo::Global; 526 527 // Define the copy symbol in the bss section and resolve it 528 LDSymbol* cpySym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 529 pSym.name(), 530 (ResolveInfo::Type)pSym.type(), 531 ResolveInfo::Define, 532 binding, 533 pSym.size(), // size 534 0x0, // value 535 FragmentRef::Create(*frag, 0x0), 536 (ResolveInfo::Visibility)pSym.other()); 537 538 // Output all other alias symbols if any 539 Module::AliasList* alias_list = pBuilder.getModule().getAliasList(pSym); 540 if (NULL == alias_list) 541 return *cpySym; 542 543 for (Module::alias_iterator it = alias_list->begin(), ie = alias_list->end(); 544 it != ie; ++it) { 545 const ResolveInfo* alias = *it; 546 if (alias == &pSym || !alias->isDyn()) 547 continue; 548 549 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 550 alias->name(), 551 (ResolveInfo::Type)alias->type(), 552 ResolveInfo::Define, 553 binding, 554 alias->size(), // size 555 0x0, // value 556 FragmentRef::Create(*frag, 0x0), 557 (ResolveInfo::Visibility)alias->other()); 558 } 559 560 return *cpySym; 561} 562 563void MipsRelocator::postponeRelocation(Relocation& pReloc) 564{ 565 ResolveInfo* rsym = pReloc.symInfo(); 566 m_PostponedRelocs[rsym].insert(&pReloc); 567} 568 569void MipsRelocator::applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc) 570{ 571 m_CurrentLo16Reloc = &pLo16Reloc; 572 573 ResolveInfo* rsym = pLo16Reloc.parent().symInfo(); 574 575 RelocationSet & relocs = m_PostponedRelocs[rsym]; 576 for (RelocationSet::iterator it = relocs.begin(); it != relocs.end(); ++it) 577 (*it)->apply(*this); 578 579 m_PostponedRelocs.erase(rsym); 580 581 m_CurrentLo16Reloc = NULL; 582} 583 584bool MipsRelocator::isGpDisp(const Relocation& pReloc) const 585{ 586 return 0 == strcmp("_gp_disp", pReloc.symInfo()->name()); 587} 588 589bool MipsRelocator::isRel() const 590{ 591 return config().targets().is32Bits(); 592} 593 594bool MipsRelocator::isLocalReloc(ResolveInfo& pSym) const 595{ 596 if (pSym.isUndef()) 597 return false; 598 599 return pSym.isLocal() || 600 !getTarget().isDynamicSymbol(pSym) || 601 !pSym.isDyn(); 602} 603 604Relocator::Address MipsRelocator::getGPAddress() 605{ 606 return getTarget().getGOT().getGPAddr(getApplyingInput()); 607} 608 609Relocator::Address MipsRelocator::getGP0() 610{ 611 return getTarget().getGP0(getApplyingInput()); 612} 613 614Fragment& MipsRelocator::getLocalGOTEntry(MipsRelocationInfo& pReloc, 615 Relocation::DWord entryValue) 616{ 617 // rsym - The relocation target symbol 618 ResolveInfo* rsym = pReloc.parent().symInfo(); 619 MipsGOT& got = getTarget().getGOT(); 620 621 assert(isLocalReloc(*rsym) && 622 "Attempt to get a global GOT entry for the local relocation"); 623 624 Fragment* got_entry = got.lookupLocalEntry(rsym, entryValue); 625 626 // Found a mapping, then return the mapped entry immediately. 627 if (NULL != got_entry) 628 return *got_entry; 629 630 // Not found. 631 got_entry = got.consumeLocal(); 632 633 if (got.isPrimaryGOTConsumed()) 634 setupRelDynEntry(*FragmentRef::Create(*got_entry, 0), NULL); 635 else 636 got.setEntryValue(got_entry, entryValue); 637 638 got.recordLocalEntry(rsym, entryValue, got_entry); 639 640 return *got_entry; 641} 642 643Fragment& MipsRelocator::getGlobalGOTEntry(MipsRelocationInfo& pReloc) 644{ 645 // rsym - The relocation target symbol 646 ResolveInfo* rsym = pReloc.parent().symInfo(); 647 MipsGOT& got = getTarget().getGOT(); 648 649 assert(!isLocalReloc(*rsym) && 650 "Attempt to get a local GOT entry for the global relocation"); 651 652 Fragment* got_entry = got.lookupGlobalEntry(rsym); 653 654 // Found a mapping, then return the mapped entry immediately. 655 if (NULL != got_entry) 656 return *got_entry; 657 658 // Not found. 659 got_entry = got.consumeGlobal(); 660 661 if (got.isPrimaryGOTConsumed()) 662 setupRelDynEntry(*FragmentRef::Create(*got_entry, 0), rsym); 663 else 664 got.setEntryValue(got_entry, pReloc.parent().symValue()); 665 666 got.recordGlobalEntry(rsym, got_entry); 667 668 return *got_entry; 669} 670 671Relocator::Address MipsRelocator::getGOTOffset(MipsRelocationInfo& pReloc) 672{ 673 ResolveInfo* rsym = pReloc.parent().symInfo(); 674 MipsGOT& got = getTarget().getGOT(); 675 676 if (isLocalReloc(*rsym)) { 677 uint64_t value = pReloc.S(); 678 679 if (ResolveInfo::Section == rsym->type()) 680 value += pReloc.A(); 681 682 return got.getGPRelOffset(getApplyingInput(), 683 getLocalGOTEntry(pReloc, value)); 684 } 685 else { 686 return got.getGPRelOffset(getApplyingInput(), getGlobalGOTEntry(pReloc)); 687 } 688} 689 690void MipsRelocator::createDynRel(MipsRelocationInfo& pReloc) 691{ 692 Relocator::DWord A = pReloc.A(); 693 Relocator::DWord S = pReloc.S(); 694 695 ResolveInfo* rsym = pReloc.parent().symInfo(); 696 697 if (isLocalReloc(*rsym)) { 698 setupRelDynEntry(pReloc.parent().targetRef(), NULL); 699 pReloc.result() = A + S; 700 } 701 else { 702 setupRelDynEntry(pReloc.parent().targetRef(), rsym); 703 // Don't add symbol value that will be resolved by the dynamic linker. 704 pReloc.result() = A; 705 } 706} 707 708uint64_t MipsRelocator::calcAHL(const MipsRelocationInfo& pHiReloc) 709{ 710 assert(NULL != m_CurrentLo16Reloc && 711 "There is no saved R_MIPS_LO16 relocation"); 712 713 uint64_t AHI = pHiReloc.A() & 0xFFFF; 714 uint64_t ALO = m_CurrentLo16Reloc->A() & 0xFFFF; 715 uint64_t AHL = (AHI << 16) + int16_t(ALO); 716 717 return AHL; 718} 719 720bool MipsRelocator::isN64ABI() const 721{ 722 return config().targets().is64Bits(); 723} 724 725uint64_t MipsRelocator::getPLTAddress(ResolveInfo& rsym) 726{ 727 assert((rsym.reserved() & MipsRelocator::ReservePLT) && 728 "Symbol does not require a PLT entry"); 729 730 SymPLTMap::const_iterator it = m_SymPLTMap.find(&rsym); 731 732 Fragment* plt; 733 734 if (it != m_SymPLTMap.end()) { 735 plt = it->second.first; 736 } 737 else { 738 plt = getTarget().getPLT().consume(); 739 740 Fragment* got = getTarget().getGOTPLT().consume(); 741 Relocation* rel = getTarget().getRelPLT().consumeEntry(); 742 743 rel->setType(llvm::ELF::R_MIPS_JUMP_SLOT); 744 rel->targetRef().assign(*got); 745 rel->setSymInfo(&rsym); 746 747 m_SymPLTMap[&rsym] = PLTDescriptor(plt, got); 748 } 749 750 return getTarget().getPLT().addr() + plt->getOffset(); 751} 752 753//===----------------------------------------------------------------------===// 754// Mips32Relocator 755//===----------------------------------------------------------------------===// 756Mips32Relocator::Mips32Relocator(Mips32GNULDBackend& pParent, 757 const LinkerConfig& pConfig) 758 : MipsRelocator(pParent, pConfig) 759{} 760 761void Mips32Relocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym) 762{ 763 Relocation& relEntry = *getTarget().getRelDyn().consumeEntry(); 764 relEntry.setType(llvm::ELF::R_MIPS_REL32); 765 relEntry.targetRef() = pFragRef; 766 relEntry.setSymInfo(pSym); 767} 768 769//===----------------------------------------------------------------------===// 770// Mips64Relocator 771//===----------------------------------------------------------------------===// 772Mips64Relocator::Mips64Relocator(Mips64GNULDBackend& pParent, 773 const LinkerConfig& pConfig) 774 : MipsRelocator(pParent, pConfig) 775{} 776 777void Mips64Relocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym) 778{ 779 Relocation::Type type = llvm::ELF::R_MIPS_REL32 | 780 llvm::ELF::R_MIPS_64 << 8; 781 // FIXME (simon): Fix dynamic relocations. 782 type = llvm::ELF::R_MIPS_NONE; 783 784 Relocation& relEntry = *getTarget().getRelDyn().consumeEntry(); 785 relEntry.setType(type); 786 relEntry.targetRef() = pFragRef; 787 relEntry.setSymInfo(pSym); 788} 789 790//=========================================// 791// Relocation functions implementation // 792//=========================================// 793 794// R_MIPS_NONE and those unsupported/deprecated relocation type 795static 796MipsRelocator::Result none(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 797{ 798 return Relocator::OK; 799} 800 801// R_MIPS_32: S + A 802static 803MipsRelocator::Result abs32(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 804{ 805 ResolveInfo* rsym = pReloc.parent().symInfo(); 806 807 Relocator::DWord A = pReloc.A(); 808 Relocator::DWord S = pReloc.S(); 809 810 LDSection& target_sect = 811 pReloc.parent().targetRef().frag()->getParent()->getSection(); 812 813 // If the flag of target section is not ALLOC, we will not scan this relocation 814 // but perform static relocation. (e.g., applying .debug section) 815 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 816 pReloc.result() = S + A; 817 return Relocator::OK; 818 } 819 820 if (rsym->reserved() & MipsRelocator::ReserveRel) { 821 pParent.createDynRel(pReloc); 822 return Relocator::OK; 823 } 824 825 pReloc.result() = S + A; 826 827 return Relocator::OK; 828} 829 830// R_MIPS_26: 831// local : ((A | ((P + 4) & 0x3F000000)) + S) >> 2 832// external: (sign–extend(A) + S) >> 2 833static 834MipsRelocator::Result rel26(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 835{ 836 ResolveInfo* rsym = pReloc.parent().symInfo(); 837 838 int32_t A = ((pReloc.parent().target() & 0x03FFFFFF) << 2); 839 int32_t P = pReloc.P(); 840 int32_t S = rsym->reserved() & MipsRelocator::ReservePLT 841 ? pParent.getPLTAddress(*rsym) 842 : pReloc.S(); 843 844 if (rsym->isLocal()) 845 pReloc.result() = A | ((P + 4) & 0x3F000000); 846 else 847 pReloc.result() = mcld::signExtend<28>(A); 848 849 pReloc.result() = (pReloc.result() + S) >> 2; 850 851 return Relocator::OK; 852} 853 854// R_MIPS_HI16: 855// local/external: ((AHL + S) - (short)(AHL + S)) >> 16 856// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 857static 858MipsRelocator::Result hi16(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 859{ 860 uint64_t AHL = pParent.calcAHL(pReloc); 861 862 if (pParent.isGpDisp(pReloc.parent())) { 863 int32_t P = pReloc.P(); 864 int32_t GP = pParent.getGPAddress(); 865 pReloc.result() = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16; 866 } 867 else { 868 int32_t S = pReloc.S(); 869 if (pParent.isN64ABI()) 870 pReloc.result() = (pReloc.A() + S + 0x8000ull) >> 16; 871 else 872 pReloc.result() = ((AHL + S) - (int16_t)(AHL + S)) >> 16; 873 } 874 875 return Relocator::OK; 876} 877 878// R_MIPS_LO16: 879// local/external: AHL + S 880// _gp_disp : AHL + GP - P + 4 881static 882MipsRelocator::Result lo16(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 883{ 884 // AHL is a combination of HI16 and LO16 addends. But R_MIPS_LO16 885 // uses low 16 bits of the AHL. That is why we do not need R_MIPS_HI16 886 // addend here. 887 int32_t AHL = (pReloc.A() & 0xFFFF); 888 889 if (pParent.isGpDisp(pReloc.parent())) { 890 int32_t P = pReloc.P(); 891 int32_t GP = pParent.getGPAddress(); 892 pReloc.result() = AHL + GP - P + 4; 893 } 894 else { 895 int32_t S = pReloc.S(); 896 pReloc.result() = AHL + S; 897 } 898 899 pParent.applyPostponedRelocations(pReloc); 900 901 return Relocator::OK; 902} 903 904// R_MIPS_GPREL16: 905// external: sign–extend(A) + S - GP 906// local : sign–extend(A) + S + GP0 – GP 907static 908MipsRelocator::Result gprel16(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 909{ 910 // Remember to add the section offset to A. 911 uint64_t A = pReloc.A(); 912 uint64_t S = pReloc.S(); 913 uint64_t GP0 = pParent.getGP0(); 914 uint64_t GP = pParent.getGPAddress(); 915 916 ResolveInfo* rsym = pReloc.parent().symInfo(); 917 if (rsym->isLocal()) 918 pReloc.result() = A + S + GP0 - GP; 919 else 920 pReloc.result() = A + S - GP; 921 922 return Relocator::OK; 923} 924 925// R_MIPS_GOT16: 926// local : G (calculate AHL and put high 16 bit to GOT) 927// external: G 928static 929MipsRelocator::Result got16(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 930{ 931 if (pReloc.parent().symInfo()->isLocal()) { 932 int32_t AHL = pParent.calcAHL(pReloc); 933 int32_t S = pReloc.S(); 934 int32_t res = (AHL + S + 0x8000) & 0xFFFF0000; 935 936 MipsGOT& got = pParent.getTarget().getGOT(); 937 938 Fragment& got_entry = pParent.getLocalGOTEntry(pReloc, res); 939 940 pReloc.result() = got.getGPRelOffset(pParent.getApplyingInput(), got_entry); 941 } 942 else { 943 pReloc.result() = pParent.getGOTOffset(pReloc); 944 } 945 946 return Relocator::OK; 947} 948 949// R_MIPS_GOTHI16: 950// external: (G - (short)G) >> 16 + A 951static 952MipsRelocator::Result gothi16(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 953{ 954 Relocator::Address G = pParent.getGOTOffset(pReloc); 955 int32_t A = pReloc.A(); 956 957 pReloc.result() = (G - (int16_t)G) >> (16 + A); 958 959 return Relocator::OK; 960} 961 962// R_MIPS_GOTLO16: 963// external: G & 0xffff 964static 965MipsRelocator::Result gotlo16(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 966{ 967 pReloc.result() = pParent.getGOTOffset(pReloc) & 0xffff; 968 969 return Relocator::OK; 970} 971 972// R_MIPS_SUB: 973// external/local: S - A 974static 975MipsRelocator::Result sub(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 976{ 977 uint64_t S = pReloc.S(); 978 uint64_t A = pReloc.A(); 979 980 pReloc.result() = S - A; 981 982 return Relocator::OK; 983} 984 985// R_MIPS_CALL16: G 986static 987MipsRelocator::Result call16(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 988{ 989 pReloc.result() = pParent.getGOTOffset(pReloc); 990 991 return Relocator::OK; 992} 993 994// R_MIPS_GPREL32: A + S + GP0 - GP 995static 996MipsRelocator::Result gprel32(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 997{ 998 // Remember to add the section offset to A. 999 uint64_t A = pReloc.A(); 1000 uint64_t S = pReloc.S(); 1001 uint64_t GP0 = pParent.getGP0(); 1002 uint64_t GP = pParent.getGPAddress(); 1003 1004 pReloc.result() = A + S + GP0 - GP; 1005 1006 return Relocator::OK; 1007} 1008 1009// R_MIPS_64: S + A 1010static 1011MipsRelocator::Result abs64(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1012{ 1013 // FIXME (simon): Consider to merge with abs32() or use the same function 1014 // but with another mask size. 1015 ResolveInfo* rsym = pReloc.parent().symInfo(); 1016 1017 Relocator::DWord A = pReloc.A(); 1018 Relocator::DWord S = pReloc.S(); 1019 1020 LDSection& target_sect = 1021 pReloc.parent().targetRef().frag()->getParent()->getSection(); 1022 1023 // If the flag of target section is not ALLOC, we will not scan this relocation 1024 // but perform static relocation. (e.g., applying .debug section) 1025 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1026 pReloc.result() = S + A; 1027 return Relocator::OK; 1028 } 1029 1030 if (rsym->reserved() & MipsRelocator::ReserveRel) { 1031 pParent.createDynRel(pReloc); 1032 return Relocator::OK; 1033 } 1034 1035 pReloc.result() = S + A; 1036 1037 return Relocator::OK; 1038} 1039 1040// R_MIPS_GOT_DISP / R_MIPS_GOT_PAGE: G 1041static 1042MipsRelocator::Result gotdisp(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1043{ 1044 pReloc.result() = pParent.getGOTOffset(pReloc); 1045 1046 return Relocator::OK; 1047} 1048 1049// R_MIPS_GOT_OFST: 1050static 1051MipsRelocator::Result gotoff(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1052{ 1053 // FIXME (simon): Needs to be implemented. 1054 return Relocator::OK; 1055} 1056 1057// R_MIPS_JALR: 1058static 1059MipsRelocator::Result jalr(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1060{ 1061 return Relocator::OK; 1062} 1063 1064// R_MIPS_LA25_LUI 1065static 1066MipsRelocator::Result la25lui(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1067{ 1068 int32_t S = pReloc.S(); 1069 1070 pReloc.result() = (S + 0x8000) >> 16; 1071 1072 return Relocator::OK; 1073} 1074 1075// R_MIPS_LA25_J 1076static 1077MipsRelocator::Result la25j(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1078{ 1079 int32_t S = pReloc.S(); 1080 1081 pReloc.result() = S >> 2; 1082 1083 return Relocator::OK; 1084} 1085 1086// R_MIPS_LA25_ADD 1087static 1088MipsRelocator::Result la25add(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1089{ 1090 pReloc.result() = pReloc.S(); 1091 1092 return Relocator::OK; 1093} 1094 1095// R_MIPS_PC32: 1096static 1097MipsRelocator::Result pc32(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1098{ 1099 return Relocator::OK; 1100} 1101 1102static 1103MipsRelocator::Result unsupport(MipsRelocationInfo& pReloc, MipsRelocator& pParent) 1104{ 1105 return Relocator::Unsupport; 1106} 1107