1//===- ARMRelocationFactory.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 10#include <llvm/ADT/Twine.h> 11#include <llvm/Support/DataTypes.h> 12#include <llvm/Support/ELF.h> 13#include <llvm/Support/Host.h> 14#include <mcld/MC/MCLDInfo.h> 15#include <mcld/LD/Layout.h> 16#include <mcld/Support/MsgHandling.h> 17 18#include "ARMRelocationFactory.h" 19#include "ARMRelocationFunctions.h" 20 21using namespace mcld; 22 23//===--------------------------------------------------------------------===// 24// Relocation Functions and Tables 25//===--------------------------------------------------------------------===// 26DECL_ARM_APPLY_RELOC_FUNCS 27 28/// the prototype of applying function 29typedef RelocationFactory::Result (*ApplyFunctionType)( 30 Relocation& pReloc, 31 const MCLDInfo& pLDInfo, 32 ARMRelocationFactory& pParent); 33 34// the table entry of applying functions 35struct ApplyFunctionTriple 36{ 37 ApplyFunctionType func; 38 unsigned int type; 39 const char* name; 40}; 41 42// declare the table of applying functions 43static const ApplyFunctionTriple ApplyFunctions[] = { 44 DECL_ARM_APPLY_RELOC_FUNC_PTRS 45}; 46 47//===--------------------------------------------------------------------===// 48// ARMRelocationFactory 49//===--------------------------------------------------------------------===// 50ARMRelocationFactory::ARMRelocationFactory(size_t pNum, 51 ARMGNULDBackend& pParent) 52 : RelocationFactory(pNum), 53 m_Target(pParent) { 54} 55 56ARMRelocationFactory::~ARMRelocationFactory() 57{ 58} 59 60RelocationFactory::Result 61ARMRelocationFactory::applyRelocation(Relocation& pRelocation, 62 const MCLDInfo& pLDInfo) 63{ 64 Relocation::Type type = pRelocation.type(); 65 if (type > 130) { // 131-255 doesn't noted in ARM spec 66 fatal(diag::unknown_relocation) << (int)type 67 << pRelocation.symInfo()->name(); 68 return RelocationFactory::Unknown; 69 } 70 71 return ApplyFunctions[type].func(pRelocation, pLDInfo, *this); 72} 73 74const char* ARMRelocationFactory::getName(RelocationFactory::Type pType) const 75{ 76 return ApplyFunctions[pType].name; 77} 78 79//===--------------------------------------------------------------------===// 80// non-member functions 81static RelocationFactory::DWord getThumbBit(const Relocation& pReloc) 82{ 83 // Set thumb bit if 84 // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set 85 RelocationFactory::DWord thumbBit = 86 ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) && 87 (pReloc.symInfo()->type() == ResolveInfo::Function) && 88 ((pReloc.symValue() & 0x1) != 0))? 89 1:0; 90 return thumbBit; 91} 92 93 94 95 96//=========================================// 97// Relocation helper function // 98//=========================================// 99 100// Using uint64_t to make sure those complicate operations won't cause 101// undefined behavior. 102static 103uint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width) 104{ 105 assert(pOri_width <= 64); 106 uint64_t sign_bit = 1 << (pOri_width - 1); 107 return (pVal ^ sign_bit) - sign_bit; 108 // Reverse sign bit, then subtract sign bit. 109} 110 111static 112uint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask) 113{ 114 return (pA & ~pMask) | (pB & pMask) ; 115} 116 117// Check if symbol can use relocation R_ARM_RELATIVE 118static bool 119helper_use_relative_reloc(const ResolveInfo& pSym, 120 const MCLDInfo& pLDInfo, 121 const ARMRelocationFactory& pFactory) 122{ 123 // if symbol is dynamic or undefine or preemptible 124 if (pSym.isDyn() || 125 pSym.isUndef() || 126 pFactory.getTarget().isSymbolPreemptible(pSym, 127 pLDInfo, 128 pLDInfo.output())) 129 return false; 130 return true; 131} 132 133static 134GOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 135 const MCLDInfo& pLDInfo, 136 ARMRelocationFactory& pParent) 137{ 138 // rsym - The relocation target symbol 139 ResolveInfo* rsym = pReloc.symInfo(); 140 ARMGNULDBackend& ld_backend = pParent.getTarget(); 141 142 bool exist; 143 GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist); 144 if (!exist) { 145 // If we first get this GOT entry, we should initialize it. 146 if (rsym->reserved() & ARMGNULDBackend::ReserveGOT) { 147 // No corresponding dynamic relocation, initialize to the symbol value. 148 got_entry.setContent(pReloc.symValue()); 149 } 150 else if (rsym->reserved() & ARMGNULDBackend::GOTRel) { 151 152 // Initialize corresponding dynamic relocation. 153 Relocation& rel_entry = 154 *ld_backend.getRelDyn().getEntry(*rsym, true, exist); 155 assert(!exist && "GOT entry not exist, but DynRel entry exist!"); 156 if ( rsym->isLocal() || 157 helper_use_relative_reloc(*rsym, pLDInfo, pParent)) { 158 // Initialize got entry to target symbol address 159 got_entry.setContent(pReloc.symValue()); 160 rel_entry.setType(llvm::ELF::R_ARM_RELATIVE); 161 rel_entry.setSymInfo(0); 162 } 163 else { 164 // Initialize got entry to 0 for corresponding dynamic relocation. 165 got_entry.setContent(0); 166 rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT); 167 rel_entry.setSymInfo(rsym); 168 } 169 rel_entry.targetRef().assign(got_entry); 170 } 171 else { 172 fatal(diag::reserve_entry_number_mismatch_got); 173 } 174 } 175 return got_entry; 176} 177 178static 179ARMRelocationFactory::Address helper_GOT_ORG(ARMRelocationFactory& pParent) 180{ 181 return pParent.getTarget().getGOT().getSection().addr(); 182} 183 184 185static 186ARMRelocationFactory::Address helper_GOT(Relocation& pReloc, 187 const MCLDInfo& pLDInfo, 188 ARMRelocationFactory& pParent) 189{ 190 GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo, pParent); 191 return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry); 192} 193 194 195static 196PLTEntry& helper_get_PLT_and_init(Relocation& pReloc, 197 ARMRelocationFactory& pParent) 198{ 199 // rsym - The relocation target symbol 200 ResolveInfo* rsym = pReloc.symInfo(); 201 ARMGNULDBackend& ld_backend = pParent.getTarget(); 202 203 bool exist; 204 PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist); 205 if (!exist) { 206 // If we first get this PLT entry, we should initialize it. 207 if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 208 GOTEntry& gotplt_entry = 209 *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist); 210 // Initialize corresponding dynamic relocation. 211 Relocation& rel_entry = 212 *ld_backend.getRelPLT().getEntry(*rsym, true, exist); 213 assert(!exist && "PLT entry not exist, but DynRel entry exist!"); 214 rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT); 215 rel_entry.targetRef().assign(gotplt_entry); 216 rel_entry.setSymInfo(rsym); 217 } 218 else { 219 fatal(diag::reserve_entry_number_mismatch_plt); 220 } 221 } 222 return plt_entry; 223} 224 225 226 227static 228ARMRelocationFactory::Address helper_PLT_ORG(ARMRelocationFactory& pParent) 229{ 230 return pParent.getTarget().getPLT().getSection().addr(); 231} 232 233 234static 235ARMRelocationFactory::Address helper_PLT(Relocation& pReloc, 236 ARMRelocationFactory& pParent) 237{ 238 PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 239 return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry); 240} 241 242// Get an relocation entry in .rel.dyn and set its type to pType, 243// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo() 244static 245void helper_DynRel(Relocation& pReloc, 246 ARMRelocationFactory::Type pType, 247 ARMRelocationFactory& pParent) 248{ 249 // rsym - The relocation target symbol 250 ResolveInfo* rsym = pReloc.symInfo(); 251 ARMGNULDBackend& ld_backend = pParent.getTarget(); 252 bool exist; 253 254 Relocation& rel_entry = 255 *ld_backend.getRelDyn().getEntry(*rsym, false, exist); 256 rel_entry.setType(pType); 257 rel_entry.targetRef() = pReloc.targetRef(); 258 259 if (pType == llvm::ELF::R_ARM_RELATIVE) 260 rel_entry.setSymInfo(0); 261 else 262 rel_entry.setSymInfo(rsym); 263} 264 265static ARMRelocationFactory::DWord 266helper_extract_movw_movt_addend(ARMRelocationFactory::DWord pTarget) 267{ 268 // imm16: [19-16][11-0] 269 return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU), 270 16); 271} 272 273static ARMRelocationFactory::DWord 274helper_insert_val_movw_movt_inst(ARMRelocationFactory::DWord pTarget, 275 ARMRelocationFactory::DWord pImm) 276{ 277 // imm16: [19-16][11-0] 278 pTarget &= 0xfff0f000U; 279 pTarget |= pImm & 0x0fffU; 280 pTarget |= (pImm & 0xf000U) << 4; 281 return pTarget; 282} 283 284static ARMRelocationFactory::DWord 285helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pTarget) 286{ 287 // Consider the endianness problem, get the target data value from lower 288 // and upper 16 bits 289 ARMRelocationFactory::DWord val = 290 (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) | 291 *(reinterpret_cast<uint16_t*>(&pTarget) + 1); 292 293 // imm16: [19-16][26][14-12][7-0] 294 return helper_sign_extend((((val >> 4) & 0xf000U) | 295 ((val >> 15) & 0x0800U) | 296 ((val >> 4) & 0x0700U) | 297 (val & 0x00ffU)), 298 16); 299} 300 301static ARMRelocationFactory::DWord 302helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pTarget, 303 ARMRelocationFactory::DWord pImm) 304{ 305 ARMRelocationFactory::DWord val; 306 // imm16: [19-16][26][14-12][7-0] 307 pTarget &= 0xfbf08f00U; 308 pTarget |= (pImm & 0xf000U) << 4; 309 pTarget |= (pImm & 0x0800U) << 15; 310 pTarget |= (pImm & 0x0700U) << 4; 311 pTarget |= (pImm & 0x00ffU); 312 313 // Consider the endianness problem, write back data from lower and 314 // upper 16 bits 315 val = (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) | 316 *(reinterpret_cast<uint16_t*>(&pTarget) + 1); 317 return val; 318} 319 320static ARMRelocationFactory::DWord 321helper_thumb32_branch_offset(ARMRelocationFactory::DWord pUpper16, 322 ARMRelocationFactory::DWord pLower16) 323{ 324 ARMRelocationFactory::DWord s = (pUpper16 & (1U << 10)) >> 10, // 26 bit 325 u = pUpper16 & 0x3ffU, // 25-16 326 l = pLower16 & 0x7ffU, // 10-0 327 j1 = (pLower16 & (1U << 13)) >> 13, // 13 328 j2 = (pLower16 & (1U << 11)) >> 11; // 11 329 ARMRelocationFactory::DWord i1 = j1 ^ s? 0: 1, 330 i2 = j2 ^ s? 0: 1; 331 332 // [31-25][24][23][22][21-12][11-1][0] 333 // 0 s i1 i2 u l 0 334 return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) | 335 (u << 12) | (l << 1), 336 25); 337} 338 339static ARMRelocationFactory::DWord 340helper_thumb32_branch_upper(ARMRelocationFactory::DWord pUpper16, 341 ARMRelocationFactory::DWord pOffset) 342{ 343 uint32_t sign = ((pOffset & 0x80000000U) >> 31); 344 return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10); 345} 346 347static ARMRelocationFactory::DWord 348helper_thumb32_branch_lower(ARMRelocationFactory::DWord pLower16, 349 ARMRelocationFactory::DWord pOffset) 350{ 351 uint32_t sign = ((pOffset & 0x80000000U) >> 31); 352 return ((pLower16 & ~0x2fffU) | 353 ((((pOffset >> 23) & 1) ^ !sign) << 13) | 354 ((((pOffset >> 22) & 1) ^ !sign) << 11) | 355 ((pOffset >> 1) & 0x7ffU)); 356} 357 358// Return true if overflow 359static bool 360helper_check_signed_overflow(ARMRelocationFactory::DWord pValue, 361 unsigned bits) 362{ 363 int32_t signed_val = static_cast<int32_t>(pValue); 364 int32_t max = (1 << (bits - 1)) - 1; 365 int32_t min = -(1 << (bits - 1)); 366 if (signed_val > max || signed_val < min) { 367 return true; 368 } else { 369 return false; 370 } 371} 372 373 374//=========================================// 375// Each relocation function implementation // 376//=========================================// 377 378// R_ARM_NONE 379ARMRelocationFactory::Result none(Relocation& pReloc, 380 const MCLDInfo& pLDInfo, 381 ARMRelocationFactory& pParent) 382{ 383 return ARMRelocationFactory::OK; 384} 385 386// R_ARM_ABS32: (S + A) | T 387ARMRelocationFactory::Result abs32(Relocation& pReloc, 388 const MCLDInfo& pLDInfo, 389 ARMRelocationFactory& pParent) 390{ 391 ResolveInfo* rsym = pReloc.symInfo(); 392 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 393 ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 394 ARMRelocationFactory::DWord S = pReloc.symValue(); 395 396 const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 397 *(pReloc.targetRef().frag())); 398 assert(NULL != target_sect); 399 400 // If the flag of target section is not ALLOC, we will not scan this relocation 401 // but perform static relocation. (e.g., applying .debug section) 402 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 403 pReloc.target() = (S + A) | T; 404 return ARMRelocationFactory::OK; 405 } 406 407 // A local symbol may need REL Type dynamic relocation 408 if (rsym->isLocal() && (rsym->reserved() & ARMGNULDBackend::ReserveRel)) { 409 helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent); 410 pReloc.target() = (S + A) | T ; 411 return ARMRelocationFactory::OK; 412 } 413 414 // An external symbol may need PLT and dynamic relocation 415 if (!rsym->isLocal()) { 416 if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 417 S = helper_PLT(pReloc, pParent); 418 T = 0 ; // PLT is not thumb 419 pReloc.target() = (S + A) | T; 420 } 421 // If we generate a dynamic relocation (except R_ARM_RELATIVE) 422 // for a place, we should not perform static relocation on it 423 // in order to keep the addend store in the place correct. 424 if (rsym->reserved() & ARMGNULDBackend::ReserveRel) { 425 if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) { 426 helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent); 427 } 428 else { 429 helper_DynRel(pReloc, pReloc.type(), pParent); 430 return ARMRelocationFactory::OK; 431 } 432 } 433 } 434 435 436 // perform static relocation 437 pReloc.target() = (S + A) | T; 438 return ARMRelocationFactory::OK; 439} 440 441// R_ARM_REL32: ((S + A) | T) - P 442ARMRelocationFactory::Result rel32(Relocation& pReloc, 443 const MCLDInfo& pLDInfo, 444 ARMRelocationFactory& pParent) 445{ 446 // perform static relocation 447 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 448 ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 449 pReloc.target() = ((pReloc.symValue() + A) | T) 450 - pReloc.place(pParent.getLayout()); 451 return ARMRelocationFactory::OK; 452} 453 454// R_ARM_BASE_PREL: B(S) + A - P 455ARMRelocationFactory::Result base_prel(Relocation& pReloc, 456 const MCLDInfo& pLDInfo, 457 ARMRelocationFactory& pParent) 458{ 459 // perform static relocation 460 ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 461 pReloc.target() = pReloc.symValue() + A - pReloc.place(pParent.getLayout()); 462 return ARMRelocationFactory::OK; 463} 464 465// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG 466ARMRelocationFactory::Result gotoff32(Relocation& pReloc, 467 const MCLDInfo& pLDInfo, 468 ARMRelocationFactory& pParent) 469{ 470 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 471 ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 472 ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); 473 ARMRelocationFactory::Address S = pReloc.symValue(); 474 475 pReloc.target() = ((S + A) | T) - GOT_ORG; 476 return ARMRelocationFactory::OK; 477} 478 479// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG 480ARMRelocationFactory::Result got_brel(Relocation& pReloc, 481 const MCLDInfo& pLDInfo, 482 ARMRelocationFactory& pParent) 483{ 484 if (!(pReloc.symInfo()->reserved() & 485 (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) { 486 return ARMRelocationFactory::BadReloc; 487 } 488 ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent); 489 ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 490 ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); 491 // Apply relocation. 492 pReloc.target() = GOT_S + A - GOT_ORG; 493 return ARMRelocationFactory::OK; 494} 495 496// R_ARM_GOT_PREL: GOT(S) + A - P 497ARMRelocationFactory::Result got_prel(Relocation& pReloc, 498 const MCLDInfo& pLDInfo, 499 ARMRelocationFactory& pParent) 500{ 501 if (!(pReloc.symInfo()->reserved() & 502 (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) { 503 return ARMRelocationFactory::BadReloc; 504 } 505 ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent); 506 ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend(); 507 ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout()); 508 // Apply relocation. 509 pReloc.target() = GOT_S + A - P; 510 return ARMRelocationFactory::OK; 511} 512 513// R_ARM_PLT32: ((S + A) | T) - P 514// R_ARM_JUMP24: ((S + A) | T) - P 515// R_ARM_CALL: ((S + A) | T) - P 516ARMRelocationFactory::Result call(Relocation& pReloc, 517 const MCLDInfo& pLDInfo, 518 ARMRelocationFactory& pParent) 519{ 520 // TODO: Some issue have not been considered: 521 // 1. Add stub when switching mode or jump target too far 522 // 2. We assume the blx is available 523 524 // If target is undefined weak symbol, we only need to jump to the 525 // next instruction unless it has PLT entry. Rewrite instruction 526 // to NOP. 527 if (pReloc.symInfo()->isWeak() && 528 pReloc.symInfo()->isUndef() && 529 !pReloc.symInfo()->isDyn() && 530 !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) { 531 // change target to NOP : mov r0, r0 532 pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000; 533 return ARMRelocationFactory::OK; 534 } 535 536 ARMRelocationFactory::Address S; // S depends on PLT exists or not. 537 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 538 ARMRelocationFactory::DWord A = 539 helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26) 540 + pReloc.addend(); 541 ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout()); 542 543 S = pReloc.symValue(); 544 if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) { 545 S = helper_PLT(pReloc, pParent); 546 T = 0; // PLT is not thumb. 547 } 548 549 // If the jump target is thumb instruction, switch mode is needed, rewrite 550 // the instruction to BLX 551 if (T != 0) { 552 // cannot rewrite R_ARM_JUMP24 instruction to blx 553 assert((pReloc.type() != llvm::ELF::R_ARM_JUMP24)&& 554 "Invalid instruction to rewrite to blx for switching mode."); 555 pReloc.target() = (pReloc.target() & 0xffffff) | 556 0xfa000000 | 557 (((S + A - P) & 2) << 23); 558 } 559 560 ARMRelocationFactory::DWord X = ((S + A) | T) - P; 561 // Check X is 24bit sign int. If not, we should use stub or PLT before apply. 562 if (helper_check_signed_overflow(X, 26)) 563 return ARMRelocationFactory::Overflow; 564 // Make sure the Imm is 0. Result Mask. 565 pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2); 566 return ARMRelocationFactory::OK; 567} 568 569// R_ARM_THM_CALL: ((S + A) | T) - P 570// R_ARM_THM_JUMP24: (((S + A) | T) - P) 571ARMRelocationFactory::Result thm_call(Relocation& pReloc, 572 const MCLDInfo& pLDInfo, 573 ARMRelocationFactory& pParent) 574{ 575 // If target is undefined weak symbol, we only need to jump to the 576 // next instruction unless it has PLT entry. Rewrite instruction 577 // to NOP. 578 if (pReloc.symInfo()->isWeak() && 579 pReloc.symInfo()->isUndef() && 580 !pReloc.symInfo()->isDyn() && 581 !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) { 582 pReloc.target() = (0xe000U << 16) | 0xbf00U; 583 return ARMRelocationFactory::OK; 584 } 585 586 // get lower and upper 16 bit instructions from relocation targetData 587 uint16_t upper16 = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 588 uint16_t lower16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 589 590 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 591 ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper16, 592 lower16); 593 ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout()); 594 ARMRelocationFactory::Address S; 595 596 // if symbol has plt 597 if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) { 598 S = helper_PLT(pReloc, pParent); 599 T = 0; // PLT is not thumb. 600 } 601 else { 602 S = pReloc.symValue(); 603 } 604 605 S = S + A; 606 607 // FIXME: check if we can use BLX instruction (check from .ARM.attribute 608 // CPU ARCH TAG, which should be ARMv5 or above) 609 610 // If the jump target is not thumb, switch mode is needed, rewrite 611 // instruction to BLX 612 if (T == 0) { 613 // for BLX, select bit 1 from relocation base address to jump target 614 // address 615 S = helper_bit_select(S, P, 0x2); 616 // rewrite instruction to BLX 617 lower16 &= ~0x1000U; 618 } 619 else { 620 // otherwise, the instruction should be BL 621 lower16 |= 0x1000U; 622 } 623 624 ARMRelocationFactory::DWord X = (S | T) - P; 625 626 // TODO: check if we need stub when building non-shared object, 627 // overflow or switch-mode. 628 629 // FIXME: Check bit size is 24(thumb2) or 22? 630 if (helper_check_signed_overflow(X, 25)) { 631 return ARMRelocationFactory::Overflow; 632 } 633 634 upper16 = helper_thumb32_branch_upper(upper16, X); 635 lower16 = helper_thumb32_branch_lower(lower16, X); 636 637 *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper16; 638 *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower16; 639 640 return ARMRelocationFactory::OK; 641} 642 643// R_ARM_MOVW_ABS_NC: (S + A) | T 644ARMRelocationFactory::Result movw_abs_nc(Relocation& pReloc, 645 const MCLDInfo& pLDInfo, 646 ARMRelocationFactory& pParent) 647{ 648 ResolveInfo* rsym = pReloc.symInfo(); 649 ARMRelocationFactory::Address S = pReloc.symValue(); 650 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 651 ARMRelocationFactory::DWord A = 652 helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 653 ARMRelocationFactory::DWord X; 654 655 const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 656 *(pReloc.targetRef().frag())); 657 assert(NULL != target_sect); 658 // If the flag of target section is not ALLOC, we will not scan this 659 // relocation but perform static relocation. (e.g., applying .debug section) 660 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 661 // use plt 662 if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 663 S = helper_PLT(pReloc, pParent); 664 T = 0 ; // PLT is not thumb 665 } 666 } 667 668 // perform static relocation 669 X = (S + A) | T; 670 pReloc.target() = helper_insert_val_movw_movt_inst( 671 pReloc.target() + pReloc.addend(), X); 672 return ARMRelocationFactory::OK; 673} 674 675// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P 676ARMRelocationFactory::Result movw_prel_nc(Relocation& pReloc, 677 const MCLDInfo& pLDInfo, 678 ARMRelocationFactory& pParent) 679{ 680 ARMRelocationFactory::Address S = pReloc.symValue(); 681 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 682 ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 683 ARMRelocationFactory::DWord A = 684 helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 685 ARMRelocationFactory::DWord X; 686 687 X = ((S + A) | T) - P; 688 689 if (helper_check_signed_overflow(X, 16)) { 690 return ARMRelocationFactory::Overflow; 691 } else { 692 pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 693 return ARMRelocationFactory::OK; 694 } 695} 696 697// R_ARM_MOVT_ABS: S + A 698ARMRelocationFactory::Result movt_abs(Relocation& pReloc, 699 const MCLDInfo& pLDInfo, 700 ARMRelocationFactory& pParent) 701{ 702 ResolveInfo* rsym = pReloc.symInfo(); 703 ARMRelocationFactory::Address S = pReloc.symValue(); 704 ARMRelocationFactory::DWord A = 705 helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 706 ARMRelocationFactory::DWord X; 707 708 const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 709 *(pReloc.targetRef().frag())); 710 assert(NULL != target_sect); 711 // If the flag of target section is not ALLOC, we will not scan this relocation 712 // but perform static relocation. (e.g., applying .debug section) 713 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 714 // use plt 715 if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 716 S = helper_PLT(pReloc, pParent); 717 } 718 } 719 720 X = S + A; 721 X >>= 16; 722 // perform static relocation 723 pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 724 return ARMRelocationFactory::OK; 725} 726 727// R_ARM_MOVT_PREL: S + A - P 728ARMRelocationFactory::Result movt_prel(Relocation& pReloc, 729 const MCLDInfo& pLDInfo, 730 ARMRelocationFactory& pParent) 731{ 732 ARMRelocationFactory::Address S = pReloc.symValue(); 733 ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 734 ARMRelocationFactory::DWord A = 735 helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 736 ARMRelocationFactory::DWord X; 737 738 X = S + A - P; 739 X >>= 16; 740 741 pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 742 return ARMRelocationFactory::OK; 743} 744 745// R_ARM_THM_MOVW_ABS_NC: (S + A) | T 746ARMRelocationFactory::Result thm_movw_abs_nc(Relocation& pReloc, 747 const MCLDInfo& pLDInfo, 748 ARMRelocationFactory& pParent) 749{ 750 ResolveInfo* rsym = pReloc.symInfo(); 751 ARMRelocationFactory::Address S = pReloc.symValue(); 752 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 753 ARMRelocationFactory::DWord A = 754 helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 755 ARMRelocationFactory::DWord X; 756 757 const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 758 *(pReloc.targetRef().frag())); 759 assert(NULL != target_sect); 760 // If the flag of target section is not ALLOC, we will not scan this relocation 761 // but perform static relocation. (e.g., applying .debug section) 762 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 763 // use plt 764 if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 765 S = helper_PLT(pReloc, pParent); 766 T = 0; // PLT is not thumb 767 } 768 } 769 X = (S + A) | T; 770 pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 771 X); 772 return ARMRelocationFactory::OK; 773} 774 775// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P 776ARMRelocationFactory::Result thm_movw_prel_nc(Relocation& pReloc, 777 const MCLDInfo& pLDInfo, 778 ARMRelocationFactory& pParent) 779{ 780 ARMRelocationFactory::Address S = pReloc.symValue(); 781 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 782 ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 783 ARMRelocationFactory::DWord A = 784 helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 785 ARMRelocationFactory::DWord X; 786 787 X = ((S + A) | T) - P; 788 789 // check 16-bit overflow 790 pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 791 X); 792 return ARMRelocationFactory::OK; 793} 794 795// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S) 796// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S) 797ARMRelocationFactory::Result thm_movw_brel(Relocation& pReloc, 798 const MCLDInfo& pLDInfo, 799 ARMRelocationFactory& pParent) 800{ 801 ARMRelocationFactory::Address S = pReloc.symValue(); 802 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 803 ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 804 ARMRelocationFactory::DWord A = 805 helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 806 ARMRelocationFactory::DWord X; 807 808 X = ((S + A) | T) - P; 809 810 // check 16-bit overflow 811 pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 812 X); 813 return ARMRelocationFactory::OK; 814} 815 816// R_ARM_THM_MOVT_ABS: S + A 817ARMRelocationFactory::Result thm_movt_abs(Relocation& pReloc, 818 const MCLDInfo& pLDInfo, 819 ARMRelocationFactory& pParent) 820{ 821 ResolveInfo* rsym = pReloc.symInfo(); 822 ARMRelocationFactory::Address S = pReloc.symValue(); 823 ARMRelocationFactory::DWord A = 824 helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 825 ARMRelocationFactory::DWord X; 826 827 const LDSection* target_sect = pParent.getLayout().getOutputLDSection( 828 *(pReloc.targetRef().frag())); 829 assert(NULL != target_sect); 830 // If the flag of target section is not ALLOC, we will not scan this relocation 831 // but perform static relocation. (e.g., applying .debug section) 832 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) { 833 // use plt 834 if (rsym->reserved() & ARMGNULDBackend::ReservePLT) { 835 S = helper_PLT(pReloc, pParent); 836 } 837 } 838 839 X = S + A; 840 X >>= 16; 841 842 // check 16-bit overflow 843 if (helper_check_signed_overflow(X, 16)) { 844 return ARMRelocationFactory::Overflow; 845 } else { 846 pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 847 X); 848 return ARMRelocationFactory::OK; 849 } 850} 851 852// R_ARM_THM_MOVT_PREL: S + A - P 853// R_ARM_THM_MOVT_BREL: S + A - B(S) 854ARMRelocationFactory::Result thm_movt_prel(Relocation& pReloc, 855 const MCLDInfo& pLDInfo, 856 ARMRelocationFactory& pParent) 857{ 858 ARMRelocationFactory::Address S = pReloc.symValue(); 859 ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout()); 860 ARMRelocationFactory::DWord A = 861 helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend(); 862 ARMRelocationFactory::DWord X; 863 864 X = S + A - P; 865 X >>= 16; 866 pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(), 867 X); 868 return ARMRelocationFactory::OK; 869} 870 871// R_ARM_PREL31: (S + A) | T 872ARMRelocationFactory::Result prel31(Relocation& pReloc, 873 const MCLDInfo& pLDInfo, 874 ARMRelocationFactory& pParent) 875{ 876 ARMRelocationFactory::DWord target = pReloc.target(); 877 ARMRelocationFactory::DWord T = getThumbBit(pReloc); 878 ARMRelocationFactory::DWord A = helper_sign_extend(target, 31) + 879 pReloc.addend(); 880 ARMRelocationFactory::Address S; 881 882 S = pReloc.symValue(); 883 // if symbol has plt 884 if ( pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) { 885 S = helper_PLT(pReloc, pParent); 886 T = 0; // PLT is not thumb. 887 } 888 889 ARMRelocationFactory::DWord X = (S + A) | T ; 890 pReloc.target() = helper_bit_select(target, X, 0x7fffffffU); 891 if (helper_check_signed_overflow(X, 31)) 892 return ARMRelocationFactory::Overflow; 893 return ARMRelocationFactory::OK; 894} 895 896// R_ARM_TLS_GD32: GOT(S) + A - P 897// R_ARM_TLS_IE32: GOT(S) + A - P 898// R_ARM_TLS_LE32: S + A - tp 899ARMRelocationFactory::Result tls(Relocation& pReloc, 900 const MCLDInfo& pLDInfo, 901 ARMRelocationFactory& pParent) 902{ 903 return ARMRelocationFactory::Unsupport; 904} 905 906ARMRelocationFactory::Result unsupport(Relocation& pReloc, 907 const MCLDInfo& pLDInfo, 908 ARMRelocationFactory& pParent) 909{ 910 return ARMRelocationFactory::Unsupport; 911} 912