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