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