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 21 using namespace mcld; 22 23 //===--------------------------------------------------------------------===// 24 // Relocation Functions and Tables 25 //===--------------------------------------------------------------------===// 26 DECL_ARM_APPLY_RELOC_FUNCS 27 28 /// the prototype of applying function 29 typedef RelocationFactory::Result (*ApplyFunctionType)( 30 Relocation& pReloc, 31 const MCLDInfo& pLDInfo, 32 ARMRelocationFactory& pParent); 33 34 // the table entry of applying functions 35 struct ApplyFunctionTriple 36 { 37 ApplyFunctionType func; 38 unsigned int type; 39 const char* name; 40 }; 41 42 // declare the table of applying functions 43 static const ApplyFunctionTriple ApplyFunctions[] = { 44 DECL_ARM_APPLY_RELOC_FUNC_PTRS 45 }; 46 47 //===--------------------------------------------------------------------===// 48 // ARMRelocationFactory 49 //===--------------------------------------------------------------------===// 50 ARMRelocationFactory::ARMRelocationFactory(size_t pNum, 51 ARMGNULDBackend& pParent) 52 : RelocationFactory(pNum), 53 m_Target(pParent) { 54 } 55 56 ARMRelocationFactory::~ARMRelocationFactory() 57 { 58 } 59 60 RelocationFactory::Result 61 ARMRelocationFactory::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 74 const char* ARMRelocationFactory::getName(RelocationFactory::Type pType) const 75 { 76 return ApplyFunctions[pType].name; 77 } 78 79 //===--------------------------------------------------------------------===// 80 // non-member functions 81 static 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. 102 static 103 uint64_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 111 static 112 uint64_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 118 static bool 119 helper_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 133 static 134 GOTEntry& 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 178 static 179 ARMRelocationFactory::Address helper_GOT_ORG(ARMRelocationFactory& pParent) 180 { 181 return pParent.getTarget().getGOT().getSection().addr(); 182 } 183 184 185 static 186 ARMRelocationFactory::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 195 static 196 PLTEntry& 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 227 static 228 ARMRelocationFactory::Address helper_PLT_ORG(ARMRelocationFactory& pParent) 229 { 230 return pParent.getTarget().getPLT().getSection().addr(); 231 } 232 233 234 static 235 ARMRelocationFactory::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() 244 static 245 void 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 265 static ARMRelocationFactory::DWord 266 helper_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 273 static ARMRelocationFactory::DWord 274 helper_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 284 static ARMRelocationFactory::DWord 285 helper_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 301 static ARMRelocationFactory::DWord 302 helper_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 320 static ARMRelocationFactory::DWord 321 helper_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 339 static ARMRelocationFactory::DWord 340 helper_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 347 static ARMRelocationFactory::DWord 348 helper_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 359 static bool 360 helper_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 379 ARMRelocationFactory::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 387 ARMRelocationFactory::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 442 ARMRelocationFactory::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 455 ARMRelocationFactory::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 466 ARMRelocationFactory::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 480 ARMRelocationFactory::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 497 ARMRelocationFactory::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 516 ARMRelocationFactory::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) 571 ARMRelocationFactory::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 644 ARMRelocationFactory::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 676 ARMRelocationFactory::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 698 ARMRelocationFactory::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 728 ARMRelocationFactory::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 746 ARMRelocationFactory::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 776 ARMRelocationFactory::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) 797 ARMRelocationFactory::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 817 ARMRelocationFactory::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) 854 ARMRelocationFactory::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 872 ARMRelocationFactory::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 899 ARMRelocationFactory::Result tls(Relocation& pReloc, 900 const MCLDInfo& pLDInfo, 901 ARMRelocationFactory& pParent) 902 { 903 return ARMRelocationFactory::Unsupport; 904 } 905 906 ARMRelocationFactory::Result unsupport(Relocation& pReloc, 907 const MCLDInfo& pLDInfo, 908 ARMRelocationFactory& pParent) 909 { 910 return ARMRelocationFactory::Unsupport; 911 } 912