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