1 //===- ARMRelocator.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 <mcld/LinkerConfig.h> 11 #include <mcld/IRBuilder.h> 12 #include <llvm/ADT/Twine.h> 13 #include <llvm/Support/DataTypes.h> 14 #include <llvm/Support/ELF.h> 15 #include <llvm/Support/Host.h> 16 #include <mcld/Support/MsgHandling.h> 17 #include <mcld/LD/LDSymbol.h> 18 #include <mcld/Object/ObjectBuilder.h> 19 #include "ARMRelocator.h" 20 #include "ARMRelocationFunctions.h" 21 22 using namespace mcld; 23 24 //===--------------------------------------------------------------------===// 25 // Relocation Functions and Tables 26 //===--------------------------------------------------------------------===// 27 DECL_ARM_APPLY_RELOC_FUNCS 28 29 /// the prototype of applying function 30 typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc, 31 ARMRelocator& pParent); 32 33 // the table entry of applying functions 34 struct ApplyFunctionTriple 35 { 36 ApplyFunctionType func; 37 unsigned int type; 38 const char* name; 39 }; 40 41 // declare the table of applying functions 42 static const ApplyFunctionTriple ApplyFunctions[] = { 43 DECL_ARM_APPLY_RELOC_FUNC_PTRS 44 }; 45 46 //===--------------------------------------------------------------------===// 47 // ARMRelocator 48 //===--------------------------------------------------------------------===// 49 ARMRelocator::ARMRelocator(ARMGNULDBackend& pParent, 50 const LinkerConfig& pConfig) 51 : Relocator(pConfig), 52 m_Target(pParent) { 53 } 54 55 ARMRelocator::~ARMRelocator() 56 { 57 } 58 59 Relocator::Result 60 ARMRelocator::applyRelocation(Relocation& pRelocation) 61 { 62 Relocation::Type type = pRelocation.type(); 63 if (type > 130) { // 131-255 doesn't noted in ARM spec 64 return Relocator::Unknown; 65 } 66 67 return ApplyFunctions[type].func(pRelocation, *this); 68 } 69 70 const char* ARMRelocator::getName(Relocator::Type pType) const 71 { 72 return ApplyFunctions[pType].name; 73 } 74 75 Relocator::Size ARMRelocator::getSize(Relocation::Type pType) const 76 { 77 return 32; 78 } 79 80 void ARMRelocator::addCopyReloc(ResolveInfo& pSym) 81 { 82 Relocation& rel_entry = *getTarget().getRelDyn().consumeEntry(); 83 rel_entry.setType(llvm::ELF::R_ARM_COPY); 84 assert(pSym.outSymbol()->hasFragRef()); 85 rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 86 rel_entry.setSymInfo(&pSym); 87 } 88 89 /// defineSymbolForCopyReloc 90 /// For a symbol needing copy relocation, define a copy symbol in the BSS 91 /// section and all other reference to this symbol should refer to this 92 /// copy. 93 /// This is executed at scan relocation stage. 94 LDSymbol& 95 ARMRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 96 const ResolveInfo& pSym) 97 { 98 // get or create corresponding BSS LDSection 99 LDSection* bss_sect_hdr = NULL; 100 ELFFileFormat* file_format = getTarget().getOutputFormat(); 101 if (ResolveInfo::ThreadLocal == pSym.type()) 102 bss_sect_hdr = &file_format->getTBSS(); 103 else 104 bss_sect_hdr = &file_format->getBSS(); 105 106 // get or create corresponding BSS SectionData 107 SectionData* bss_data = NULL; 108 if (bss_sect_hdr->hasSectionData()) 109 bss_data = bss_sect_hdr->getSectionData(); 110 else 111 bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr); 112 113 // Determine the alignment by the symbol value 114 // FIXME: here we use the largest alignment 115 uint32_t addralign = config().targets().bitclass() / 8; 116 117 // allocate space in BSS for the copy symbol 118 Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 119 uint64_t size = ObjectBuilder::AppendFragment(*frag, 120 *bss_data, 121 addralign); 122 bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 123 124 // change symbol binding to Global if it's a weak symbol 125 ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 126 if (binding == ResolveInfo::Weak) 127 binding = ResolveInfo::Global; 128 129 // Define the copy symbol in the bss section and resolve it 130 LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 131 pSym.name(), 132 (ResolveInfo::Type)pSym.type(), 133 ResolveInfo::Define, 134 binding, 135 pSym.size(), // size 136 0x0, // value 137 FragmentRef::Create(*frag, 0x0), 138 (ResolveInfo::Visibility)pSym.other()); 139 140 return *cpy_sym; 141 } 142 143 /// checkValidReloc - When we attempt to generate a dynamic relocation for 144 /// ouput file, check if the relocation is supported by dynamic linker. 145 void ARMRelocator::checkValidReloc(Relocation& pReloc) const 146 { 147 // If not PIC object, no relocation type is invalid 148 if (!config().isCodeIndep()) 149 return; 150 151 switch(pReloc.type()) { 152 case llvm::ELF::R_ARM_RELATIVE: 153 case llvm::ELF::R_ARM_COPY: 154 case llvm::ELF::R_ARM_GLOB_DAT: 155 case llvm::ELF::R_ARM_JUMP_SLOT: 156 case llvm::ELF::R_ARM_ABS32: 157 case llvm::ELF::R_ARM_ABS32_NOI: 158 case llvm::ELF::R_ARM_PC24: 159 case llvm::ELF::R_ARM_TLS_DTPMOD32: 160 case llvm::ELF::R_ARM_TLS_DTPOFF32: 161 case llvm::ELF::R_ARM_TLS_TPOFF32: 162 break; 163 164 default: 165 error(diag::non_pic_relocation) << (int)pReloc.type() 166 << pReloc.symInfo()->name(); 167 break; 168 } 169 } 170 171 void 172 ARMRelocator::scanLocalReloc(Relocation& pReloc, const LDSection& pSection) 173 { 174 // rsym - The relocation target symbol 175 ResolveInfo* rsym = pReloc.symInfo(); 176 177 switch(pReloc.type()){ 178 179 // Set R_ARM_TARGET1 to R_ARM_ABS32 180 // Ref: GNU gold 1.11 arm.cc, line 9892 181 // FIXME: R_ARM_TARGET1 should be set by option --target1-rel 182 // or --target1-rel 183 case llvm::ELF::R_ARM_TARGET1: 184 pReloc.setType(llvm::ELF::R_ARM_ABS32); 185 case llvm::ELF::R_ARM_ABS32: 186 case llvm::ELF::R_ARM_ABS32_NOI: { 187 // If buiding PIC object (shared library or PIC executable), 188 // a dynamic relocations with RELATIVE type to this location is needed. 189 // Reserve an entry in .rel.dyn 190 if (config().isCodeIndep()) { 191 getTarget().getRelDyn().reserveEntry(); 192 // set Rel bit 193 rsym->setReserved(rsym->reserved() | ReserveRel); 194 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 195 } 196 return; 197 } 198 199 case llvm::ELF::R_ARM_ABS16: 200 case llvm::ELF::R_ARM_ABS12: 201 case llvm::ELF::R_ARM_THM_ABS5: 202 case llvm::ELF::R_ARM_ABS8: 203 case llvm::ELF::R_ARM_BASE_ABS: 204 case llvm::ELF::R_ARM_MOVW_ABS_NC: 205 case llvm::ELF::R_ARM_MOVT_ABS: 206 case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: 207 case llvm::ELF::R_ARM_THM_MOVT_ABS: { 208 // PIC code should not contain these kinds of relocation 209 if (config().isCodeIndep()) { 210 error(diag::non_pic_relocation) << (int)pReloc.type() 211 << pReloc.symInfo()->name(); 212 } 213 return; 214 } 215 case llvm::ELF::R_ARM_GOTOFF32: 216 case llvm::ELF::R_ARM_GOTOFF12: { 217 // FIXME: A GOT section is needed 218 return; 219 } 220 221 // Set R_ARM_TARGET2 to R_ARM_GOT_PREL 222 // Ref: GNU gold 1.11 arm.cc, line 9892 223 // FIXME: R_ARM_TARGET2 should be set by option --target2 224 case llvm::ELF::R_ARM_TARGET2: 225 pReloc.setType(llvm::ELF::R_ARM_GOT_PREL); 226 case llvm::ELF::R_ARM_GOT_BREL: 227 case llvm::ELF::R_ARM_GOT_PREL: { 228 // A GOT entry is needed for these relocation type. 229 // return if we already create GOT for this symbol 230 if (rsym->reserved() & (ReserveGOT | GOTRel)) 231 return; 232 getTarget().getGOT().reserveGOT(); 233 // If building PIC object, a dynamic relocation with 234 // type RELATIVE is needed to relocate this GOT entry. 235 // Reserve an entry in .rel.dyn 236 if (config().isCodeIndep()) { 237 // create .rel.dyn section if not exist 238 getTarget().getRelDyn().reserveEntry(); 239 // set GOTRel bit 240 rsym->setReserved(rsym->reserved() | 0x4u); 241 return; 242 } 243 // set GOT bit 244 rsym->setReserved(rsym->reserved() | 0x2u); 245 return; 246 } 247 248 case llvm::ELF::R_ARM_BASE_PREL: { 249 // FIXME: Currently we only support R_ARM_BASE_PREL against 250 // symbol _GLOBAL_OFFSET_TABLE_ 251 if (rsym != getTarget().getGOTSymbol()->resolveInfo()) 252 fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name() 253 << "mclinker (at) googlegroups.com"; 254 return; 255 } 256 case llvm::ELF::R_ARM_COPY: 257 case llvm::ELF::R_ARM_GLOB_DAT: 258 case llvm::ELF::R_ARM_JUMP_SLOT: 259 case llvm::ELF::R_ARM_RELATIVE: { 260 // These are relocation type for dynamic linker, shold not 261 // appear in object file. 262 fatal(diag::dynamic_relocation) << (int)pReloc.type(); 263 break; 264 } 265 default: { 266 break; 267 } 268 } // end switch 269 } 270 271 void ARMRelocator::scanGlobalReloc(Relocation& pReloc, 272 IRBuilder& pBuilder, 273 const LDSection& pSection) 274 { 275 // rsym - The relocation target symbol 276 ResolveInfo* rsym = pReloc.symInfo(); 277 278 switch(pReloc.type()) { 279 280 // Set R_ARM_TARGET1 to R_ARM_ABS32 281 // Ref: GNU gold 1.11 arm.cc, line 9892 282 // FIXME: R_ARM_TARGET1 should be set by option --target1-rel 283 // or --target1-rel 284 case llvm::ELF::R_ARM_TARGET1: 285 pReloc.setType(llvm::ELF::R_ARM_ABS32); 286 case llvm::ELF::R_ARM_ABS32: 287 case llvm::ELF::R_ARM_ABS16: 288 case llvm::ELF::R_ARM_ABS12: 289 case llvm::ELF::R_ARM_THM_ABS5: 290 case llvm::ELF::R_ARM_ABS8: 291 case llvm::ELF::R_ARM_BASE_ABS: 292 case llvm::ELF::R_ARM_MOVW_ABS_NC: 293 case llvm::ELF::R_ARM_MOVT_ABS: 294 case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: 295 case llvm::ELF::R_ARM_THM_MOVT_ABS: 296 case llvm::ELF::R_ARM_ABS32_NOI: { 297 // Absolute relocation type, symbol may needs PLT entry or 298 // dynamic relocation entry 299 if (getTarget().symbolNeedsPLT(*rsym)) { 300 // create plt for this symbol if it does not have one 301 if (!(rsym->reserved() & ReservePLT)){ 302 // Symbol needs PLT entry, we need to reserve a PLT entry 303 // and the corresponding GOT and dynamic relocation entry 304 // in .got and .rel.plt. (GOT entry will be reserved simultaneously 305 // when calling ARMPLT->reserveEntry()) 306 getTarget().getPLT().reserveEntry(); 307 getTarget().getRelPLT().reserveEntry(); 308 // set PLT bit 309 rsym->setReserved(rsym->reserved() | ReservePLT); 310 } 311 } 312 313 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) { 314 // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 315 getTarget().getRelDyn().reserveEntry(); 316 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 317 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 318 addCopyReloc(*cpy_sym.resolveInfo()); 319 } 320 else { 321 checkValidReloc(pReloc); 322 // set Rel bit 323 rsym->setReserved(rsym->reserved() | ReserveRel); 324 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 325 } 326 } 327 return; 328 } 329 330 case llvm::ELF::R_ARM_GOTOFF32: 331 case llvm::ELF::R_ARM_GOTOFF12: { 332 // FIXME: A GOT section is needed 333 return; 334 } 335 336 case llvm::ELF::R_ARM_BASE_PREL: 337 case llvm::ELF::R_ARM_THM_MOVW_BREL_NC: 338 case llvm::ELF::R_ARM_THM_MOVW_BREL: 339 case llvm::ELF::R_ARM_THM_MOVT_BREL: 340 // FIXME: Currently we only support these relocations against 341 // symbol _GLOBAL_OFFSET_TABLE_ 342 if (rsym != getTarget().getGOTSymbol()->resolveInfo()) { 343 fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name() 344 << "mclinker (at) googlegroups.com"; 345 } 346 case llvm::ELF::R_ARM_REL32: 347 case llvm::ELF::R_ARM_LDR_PC_G0: 348 case llvm::ELF::R_ARM_SBREL32: 349 case llvm::ELF::R_ARM_THM_PC8: 350 case llvm::ELF::R_ARM_MOVW_PREL_NC: 351 case llvm::ELF::R_ARM_MOVT_PREL: 352 case llvm::ELF::R_ARM_THM_MOVW_PREL_NC: 353 case llvm::ELF::R_ARM_THM_MOVT_PREL: 354 case llvm::ELF::R_ARM_THM_ALU_PREL_11_0: 355 case llvm::ELF::R_ARM_THM_PC12: 356 case llvm::ELF::R_ARM_REL32_NOI: 357 case llvm::ELF::R_ARM_ALU_PC_G0_NC: 358 case llvm::ELF::R_ARM_ALU_PC_G0: 359 case llvm::ELF::R_ARM_ALU_PC_G1_NC: 360 case llvm::ELF::R_ARM_ALU_PC_G1: 361 case llvm::ELF::R_ARM_ALU_PC_G2: 362 case llvm::ELF::R_ARM_LDR_PC_G1: 363 case llvm::ELF::R_ARM_LDR_PC_G2: 364 case llvm::ELF::R_ARM_LDRS_PC_G0: 365 case llvm::ELF::R_ARM_LDRS_PC_G1: 366 case llvm::ELF::R_ARM_LDRS_PC_G2: 367 case llvm::ELF::R_ARM_LDC_PC_G0: 368 case llvm::ELF::R_ARM_LDC_PC_G1: 369 case llvm::ELF::R_ARM_LDC_PC_G2: 370 case llvm::ELF::R_ARM_ALU_SB_G0_NC: 371 case llvm::ELF::R_ARM_ALU_SB_G0: 372 case llvm::ELF::R_ARM_ALU_SB_G1_NC: 373 case llvm::ELF::R_ARM_ALU_SB_G1: 374 case llvm::ELF::R_ARM_ALU_SB_G2: 375 case llvm::ELF::R_ARM_LDR_SB_G0: 376 case llvm::ELF::R_ARM_LDR_SB_G1: 377 case llvm::ELF::R_ARM_LDR_SB_G2: 378 case llvm::ELF::R_ARM_LDRS_SB_G0: 379 case llvm::ELF::R_ARM_LDRS_SB_G1: 380 case llvm::ELF::R_ARM_LDRS_SB_G2: 381 case llvm::ELF::R_ARM_LDC_SB_G0: 382 case llvm::ELF::R_ARM_LDC_SB_G1: 383 case llvm::ELF::R_ARM_LDC_SB_G2: 384 case llvm::ELF::R_ARM_MOVW_BREL_NC: 385 case llvm::ELF::R_ARM_MOVT_BREL: 386 case llvm::ELF::R_ARM_MOVW_BREL: { 387 // Relative addressing relocation, may needs dynamic relocation 388 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) { 389 // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 390 getTarget().getRelDyn().reserveEntry(); 391 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 392 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 393 addCopyReloc(*cpy_sym.resolveInfo()); 394 } 395 else { 396 checkValidReloc(pReloc); 397 // set Rel bit 398 rsym->setReserved(rsym->reserved() | ReserveRel); 399 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 400 } 401 } 402 return; 403 } 404 405 case llvm::ELF::R_ARM_PC24: 406 case llvm::ELF::R_ARM_THM_CALL: 407 case llvm::ELF::R_ARM_PLT32: 408 case llvm::ELF::R_ARM_CALL: 409 case llvm::ELF::R_ARM_JUMP24: 410 case llvm::ELF::R_ARM_THM_JUMP24: 411 case llvm::ELF::R_ARM_SBREL31: 412 case llvm::ELF::R_ARM_PREL31: 413 case llvm::ELF::R_ARM_THM_JUMP19: 414 case llvm::ELF::R_ARM_THM_JUMP6: 415 case llvm::ELF::R_ARM_THM_JUMP11: 416 case llvm::ELF::R_ARM_THM_JUMP8: { 417 // These are branch relocation (except PREL31) 418 // A PLT entry is needed when building shared library 419 420 // return if we already create plt for this symbol 421 if (rsym->reserved() & ReservePLT) 422 return; 423 424 // if the symbol's value can be decided at link time, then no need plt 425 if (getTarget().symbolFinalValueIsKnown(*rsym)) 426 return; 427 428 // if symbol is defined in the ouput file and it's not 429 // preemptible, no need plt 430 if (rsym->isDefine() && !rsym->isDyn() && 431 !getTarget().isSymbolPreemptible(*rsym)) { 432 return; 433 } 434 435 // Symbol needs PLT entry, we need to reserve a PLT entry 436 // and the corresponding GOT and dynamic relocation entry 437 // in .got and .rel.plt. (GOT entry will be reserved simultaneously 438 // when calling ARMPLT->reserveEntry()) 439 getTarget().getPLT().reserveEntry(); 440 getTarget().getRelPLT().reserveEntry(); 441 // set PLT bit 442 rsym->setReserved(rsym->reserved() | ReservePLT); 443 return; 444 } 445 446 // Set R_ARM_TARGET2 to R_ARM_GOT_PREL 447 // Ref: GNU gold 1.11 arm.cc, line 9892 448 // FIXME: R_ARM_TARGET2 should be set by option --target2 449 case llvm::ELF::R_ARM_TARGET2: 450 pReloc.setType(llvm::ELF::R_ARM_GOT_PREL); 451 case llvm::ELF::R_ARM_GOT_BREL: 452 case llvm::ELF::R_ARM_GOT_ABS: 453 case llvm::ELF::R_ARM_GOT_PREL: { 454 // Symbol needs GOT entry, reserve entry in .got 455 // return if we already create GOT for this symbol 456 if (rsym->reserved() & (ReserveGOT | GOTRel)) 457 return; 458 getTarget().getGOT().reserveGOT(); 459 // if the symbol cannot be fully resolved at link time, then we need a 460 // dynamic relocation 461 if (!getTarget().symbolFinalValueIsKnown(*rsym)) { 462 getTarget().getRelDyn().reserveEntry(); 463 // set GOTRel bit 464 rsym->setReserved(rsym->reserved() | GOTRel); 465 return; 466 } 467 // set GOT bit 468 rsym->setReserved(rsym->reserved() | ReserveGOT); 469 return; 470 } 471 472 case llvm::ELF::R_ARM_COPY: 473 case llvm::ELF::R_ARM_GLOB_DAT: 474 case llvm::ELF::R_ARM_JUMP_SLOT: 475 case llvm::ELF::R_ARM_RELATIVE: { 476 // These are relocation type for dynamic linker, shold not 477 // appear in object file. 478 fatal(diag::dynamic_relocation) << (int)pReloc.type(); 479 break; 480 } 481 default: { 482 break; 483 } 484 } // end switch 485 } 486 487 void ARMRelocator::scanRelocation(Relocation& pReloc, 488 IRBuilder& pBuilder, 489 Module& pModule, 490 LDSection& pSection) 491 { 492 // rsym - The relocation target symbol 493 ResolveInfo* rsym = pReloc.symInfo(); 494 assert(NULL != rsym && 495 "ResolveInfo of relocation not set while scanRelocation"); 496 497 pReloc.updateAddend(); 498 assert(NULL != pSection.getLink()); 499 if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 500 return; 501 502 // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation 503 // entries should be created. 504 // FIXME: Below judgements concern nothing about TLS related relocation 505 506 // rsym is local 507 if (rsym->isLocal()) 508 scanLocalReloc(pReloc, pSection); 509 510 // rsym is external 511 else 512 scanGlobalReloc(pReloc, pBuilder, pSection); 513 514 // check if we shoule issue undefined reference for the relocation target 515 // symbol 516 if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 517 fatal(diag::undefined_reference) << rsym->name(); 518 } 519 520 //===--------------------------------------------------------------------===// 521 // non-member functions 522 //===--------------------------------------------------------------------===// 523 static Relocator::DWord getThumbBit(const Relocation& pReloc) 524 { 525 // Set thumb bit if 526 // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set 527 Relocator::DWord thumbBit = 528 ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) && 529 (pReloc.symInfo()->type() == ResolveInfo::Function) && 530 ((pReloc.symValue() & 0x1) != 0))? 531 1:0; 532 return thumbBit; 533 } 534 535 //=========================================// 536 // Relocation helper function // 537 //=========================================// 538 539 // Using uint64_t to make sure those complicate operations won't cause 540 // undefined behavior. 541 static 542 uint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width) 543 { 544 assert(pOri_width <= 64); 545 if (pOri_width == 64) 546 return pVal; 547 uint64_t mask = (~((uint64_t)0)) >> (64 - pOri_width); 548 pVal &= mask; 549 // Reverse sign bit, then subtract sign bit. 550 uint64_t sign_bit = 1 << (pOri_width - 1); 551 return (pVal ^ sign_bit) - sign_bit; 552 } 553 554 static 555 uint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask) 556 { 557 return (pA & ~pMask) | (pB & pMask) ; 558 } 559 560 // Check if symbol can use relocation R_ARM_RELATIVE 561 static bool 562 helper_use_relative_reloc(const ResolveInfo& pSym, 563 const ARMRelocator& pFactory) 564 { 565 // if symbol is dynamic or undefine or preemptible 566 if (pSym.isDyn() || 567 pSym.isUndef() || 568 pFactory.getTarget().isSymbolPreemptible(pSym)) 569 return false; 570 return true; 571 } 572 573 // Strip LSB (THUMB bit) if "S" is a THUMB target. 574 static inline void helper_clear_thumb_bit(ARMRelocator::DWord& pValue) 575 { 576 pValue &= (~0x1); 577 } 578 579 static 580 ARMGOTEntry& helper_get_GOT_and_init(Relocation& pReloc, 581 ARMRelocator& pParent) 582 { 583 // rsym - The relocation target symbol 584 ResolveInfo* rsym = pReloc.symInfo(); 585 ARMGNULDBackend& ld_backend = pParent.getTarget(); 586 587 ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym); 588 if (NULL == got_entry) { 589 got_entry = ld_backend.getGOT().consumeGOT(); 590 pParent.getSymGOTMap().record(*rsym, *got_entry); 591 // If we first get this GOT entry, we should initialize it. 592 if (rsym->reserved() & ARMRelocator::ReserveGOT) { 593 // No corresponding dynamic relocation, initialize to the symbol value. 594 got_entry->setValue(pReloc.symValue()); 595 } 596 else if (rsym->reserved() & ARMRelocator::GOTRel) { 597 598 // Initialize corresponding dynamic relocation. 599 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 600 if ( rsym->isLocal() || 601 helper_use_relative_reloc(*rsym, pParent)) { 602 // Initialize got entry to target symbol address 603 got_entry->setValue(pReloc.symValue()); 604 rel_entry.setType(llvm::ELF::R_ARM_RELATIVE); 605 rel_entry.setSymInfo(0); 606 } 607 else { 608 // Initialize got entry to 0 for corresponding dynamic relocation. 609 got_entry->setValue(0); 610 rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT); 611 rel_entry.setSymInfo(rsym); 612 } 613 rel_entry.targetRef().assign(*got_entry); 614 } 615 else { 616 fatal(diag::reserve_entry_number_mismatch_got); 617 } 618 } 619 return *got_entry; 620 } 621 622 static 623 ARMRelocator::Address helper_GOT_ORG(ARMRelocator& pParent) 624 { 625 return pParent.getTarget().getGOT().addr(); 626 } 627 628 629 static 630 ARMRelocator::Address helper_GOT(Relocation& pReloc, ARMRelocator& pParent) 631 { 632 ARMGOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent); 633 return helper_GOT_ORG(pParent) + got_entry.getOffset(); 634 } 635 636 637 static 638 ARMPLT1& helper_get_PLT_and_init(Relocation& pReloc, ARMRelocator& pParent) 639 { 640 // rsym - The relocation target symbol 641 ResolveInfo* rsym = pReloc.symInfo(); 642 ARMGNULDBackend& ld_backend = pParent.getTarget(); 643 644 ARMPLT1* plt_entry = pParent.getSymPLTMap().lookUp(*rsym); 645 if (NULL != plt_entry) 646 return *plt_entry; 647 648 plt_entry = ld_backend.getPLT().consume(); 649 pParent.getSymPLTMap().record(*rsym, *plt_entry); 650 651 // If we first get this PLT entry, we should initialize it. 652 if (rsym->reserved() & ARMRelocator::ReservePLT) { 653 ARMGOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym); 654 assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!"); 655 gotplt_entry = ld_backend.getGOT().consumeGOTPLT(); 656 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 657 658 // Initialize corresponding dynamic relocation. 659 Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry(); 660 rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT); 661 rel_entry.targetRef().assign(*gotplt_entry); 662 rel_entry.setSymInfo(rsym); 663 } 664 else { 665 fatal(diag::reserve_entry_number_mismatch_plt); 666 } 667 668 return *plt_entry; 669 } 670 671 static 672 ARMRelocator::Address helper_PLT_ORG(ARMRelocator& pParent) 673 { 674 return pParent.getTarget().getPLT().addr(); 675 } 676 677 678 static 679 ARMRelocator::Address helper_PLT(Relocation& pReloc, ARMRelocator& pParent) 680 { 681 ARMPLT1& plt_entry = helper_get_PLT_and_init(pReloc, pParent); 682 return helper_PLT_ORG(pParent) + plt_entry.getOffset(); 683 } 684 685 // Get an relocation entry in .rel.dyn and set its type to pType, 686 // its FragmentRef to pReloc->targetFrag() and its ResolveInfo to 687 // pReloc->symInfo() 688 static 689 void helper_DynRel(Relocation& pReloc, 690 ARMRelocator::Type pType, 691 ARMRelocator& pParent) 692 { 693 // rsym - The relocation target symbol 694 ResolveInfo* rsym = pReloc.symInfo(); 695 ARMGNULDBackend& ld_backend = pParent.getTarget(); 696 697 Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry(); 698 rel_entry.setType(pType); 699 rel_entry.targetRef() = pReloc.targetRef(); 700 701 if (pType == llvm::ELF::R_ARM_RELATIVE) 702 rel_entry.setSymInfo(0); 703 else 704 rel_entry.setSymInfo(rsym); 705 } 706 707 static ARMRelocator::DWord 708 helper_extract_movw_movt_addend(ARMRelocator::DWord pTarget) 709 { 710 // imm16: [19-16][11-0] 711 return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU), 712 16); 713 } 714 715 static ARMRelocator::DWord 716 helper_insert_val_movw_movt_inst(ARMRelocator::DWord pTarget, 717 ARMRelocator::DWord pImm) 718 { 719 // imm16: [19-16][11-0] 720 pTarget &= 0xfff0f000U; 721 pTarget |= pImm & 0x0fffU; 722 pTarget |= (pImm & 0xf000U) << 4; 723 return pTarget; 724 } 725 726 static ARMRelocator::DWord 727 helper_extract_thumb_movw_movt_addend(ARMRelocator::DWord pValue) 728 { 729 // imm16: [19-16][26][14-12][7-0] 730 return helper_sign_extend((((pValue >> 4) & 0xf000U) | 731 ((pValue >> 15) & 0x0800U) | 732 ((pValue >> 4) & 0x0700U) | 733 (pValue& 0x00ffU)), 734 16); 735 } 736 737 static ARMRelocator::DWord 738 helper_insert_val_thumb_movw_movt_inst(ARMRelocator::DWord pValue, 739 ARMRelocator::DWord pImm) 740 { 741 // imm16: [19-16][26][14-12][7-0] 742 pValue &= 0xfbf08f00U; 743 pValue |= (pImm & 0xf000U) << 4; 744 pValue |= (pImm & 0x0800U) << 15; 745 pValue |= (pImm & 0x0700U) << 4; 746 pValue |= (pImm & 0x00ffU); 747 return pValue; 748 } 749 750 static ARMRelocator::DWord 751 helper_thumb32_branch_offset(ARMRelocator::DWord pUpper16, 752 ARMRelocator::DWord pLower16) 753 { 754 ARMRelocator::DWord s = (pUpper16 & (1U << 10)) >> 10, // 26 bit 755 u = pUpper16 & 0x3ffU, // 25-16 756 l = pLower16 & 0x7ffU, // 10-0 757 j1 = (pLower16 & (1U << 13)) >> 13, // 13 758 j2 = (pLower16 & (1U << 11)) >> 11; // 11 759 ARMRelocator::DWord i1 = j1 ^ s? 0: 1, 760 i2 = j2 ^ s? 0: 1; 761 762 // [31-25][24][23][22][21-12][11-1][0] 763 // 0 s i1 i2 u l 0 764 return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) | 765 (u << 12) | (l << 1), 766 25); 767 } 768 769 static ARMRelocator::DWord 770 helper_thumb32_branch_upper(ARMRelocator::DWord pUpper16, 771 ARMRelocator::DWord pOffset) 772 { 773 uint32_t sign = ((pOffset & 0x80000000U) >> 31); 774 return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10); 775 } 776 777 static ARMRelocator::DWord 778 helper_thumb32_branch_lower(ARMRelocator::DWord pLower16, 779 ARMRelocator::DWord pOffset) 780 { 781 uint32_t sign = ((pOffset & 0x80000000U) >> 31); 782 return ((pLower16 & ~0x2fffU) | 783 ((((pOffset >> 23) & 1) ^ !sign) << 13) | 784 ((((pOffset >> 22) & 1) ^ !sign) << 11) | 785 ((pOffset >> 1) & 0x7ffU)); 786 } 787 788 // Return true if overflow 789 static bool 790 helper_check_signed_overflow(ARMRelocator::DWord pValue, 791 unsigned bits) 792 { 793 int32_t signed_val = static_cast<int32_t>(pValue); 794 int32_t max = (1 << (bits - 1)) - 1; 795 int32_t min = -(1 << (bits - 1)); 796 if (signed_val > max || signed_val < min) { 797 return true; 798 } else { 799 return false; 800 } 801 } 802 803 804 //=========================================// 805 // Each relocation function implementation // 806 //=========================================// 807 808 // R_ARM_NONE 809 ARMRelocator::Result none(Relocation& pReloc, ARMRelocator& pParent) 810 { 811 return ARMRelocator::OK; 812 } 813 814 // R_ARM_ABS32: (S + A) | T 815 ARMRelocator::Result abs32(Relocation& pReloc, ARMRelocator& pParent) 816 { 817 ResolveInfo* rsym = pReloc.symInfo(); 818 ARMRelocator::DWord T = getThumbBit(pReloc); 819 ARMRelocator::DWord A = pReloc.target() + pReloc.addend(); 820 ARMRelocator::DWord S = pReloc.symValue(); 821 if (T != 0x0) 822 helper_clear_thumb_bit(S); 823 824 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 825 826 // If the flag of target section is not ALLOC, we will not scan this relocation 827 // but perform static relocation. (e.g., applying .debug section) 828 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 829 pReloc.target() = (S + A) | T; 830 return ARMRelocator::OK; 831 } 832 833 // A local symbol may need REL Type dynamic relocation 834 if (rsym->isLocal() && (rsym->reserved() & ARMRelocator::ReserveRel)) { 835 helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent); 836 pReloc.target() = (S + A) | T ; 837 return ARMRelocator::OK; 838 } 839 840 // An external symbol may need PLT and dynamic relocation 841 if (!rsym->isLocal()) { 842 if (rsym->reserved() & ARMRelocator::ReservePLT) { 843 S = helper_PLT(pReloc, pParent); 844 T = 0 ; // PLT is not thumb 845 } 846 // If we generate a dynamic relocation (except R_ARM_RELATIVE) 847 // for a place, we should not perform static relocation on it 848 // in order to keep the addend store in the place correct. 849 if (rsym->reserved() & ARMRelocator::ReserveRel) { 850 if (helper_use_relative_reloc(*rsym, pParent)) { 851 helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent); 852 } 853 else { 854 helper_DynRel(pReloc, pReloc.type(), pParent); 855 return ARMRelocator::OK; 856 } 857 } 858 } 859 860 861 // perform static relocation 862 pReloc.target() = (S + A) | T; 863 return ARMRelocator::OK; 864 } 865 866 // R_ARM_REL32: ((S + A) | T) - P 867 ARMRelocator::Result rel32(Relocation& pReloc, ARMRelocator& pParent) 868 { 869 // perform static relocation 870 ARMRelocator::Address S = pReloc.symValue(); 871 ARMRelocator::DWord T = getThumbBit(pReloc); 872 ARMRelocator::DWord A = pReloc.target() + pReloc.addend(); 873 if (T != 0x0) 874 helper_clear_thumb_bit(S); 875 876 // An external symbol may need PLT (this reloc is from stub) 877 if (!pReloc.symInfo()->isLocal()) { 878 if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 879 S = helper_PLT(pReloc, pParent); 880 T = 0; // PLT is not thumb. 881 } 882 } 883 884 // perform relocation 885 pReloc.target() = ((S + A) | T) - pReloc.place(); 886 887 return ARMRelocator::OK; 888 } 889 890 // R_ARM_BASE_PREL: B(S) + A - P 891 ARMRelocator::Result base_prel(Relocation& pReloc, ARMRelocator& pParent) 892 { 893 // perform static relocation 894 ARMRelocator::DWord A = pReloc.target() + pReloc.addend(); 895 pReloc.target() = pReloc.symValue() + A - pReloc.place(); 896 return ARMRelocator::OK; 897 } 898 899 // R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG 900 ARMRelocator::Result gotoff32(Relocation& pReloc, ARMRelocator& pParent) 901 { 902 ARMRelocator::DWord T = getThumbBit(pReloc); 903 ARMRelocator::DWord A = pReloc.target() + pReloc.addend(); 904 ARMRelocator::Address GOT_ORG = helper_GOT_ORG(pParent); 905 ARMRelocator::Address S = pReloc.symValue(); 906 if (T != 0x0) 907 helper_clear_thumb_bit(S); 908 909 pReloc.target() = ((S + A) | T) - GOT_ORG; 910 return ARMRelocator::OK; 911 } 912 913 // R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG 914 ARMRelocator::Result got_brel(Relocation& pReloc, ARMRelocator& pParent) 915 { 916 if (!(pReloc.symInfo()->reserved() & 917 (ARMRelocator::ReserveGOT | ARMRelocator::GOTRel))) { 918 return ARMRelocator::BadReloc; 919 } 920 ARMRelocator::Address GOT_S = helper_GOT(pReloc, pParent); 921 ARMRelocator::DWord A = pReloc.target() + pReloc.addend(); 922 ARMRelocator::Address GOT_ORG = helper_GOT_ORG(pParent); 923 // Apply relocation. 924 pReloc.target() = GOT_S + A - GOT_ORG; 925 return ARMRelocator::OK; 926 } 927 928 // R_ARM_GOT_PREL: GOT(S) + A - P 929 ARMRelocator::Result got_prel(Relocation& pReloc, ARMRelocator& pParent) 930 { 931 if (!(pReloc.symInfo()->reserved() & 932 (ARMRelocator::ReserveGOT | ARMRelocator::GOTRel))) { 933 return ARMRelocator::BadReloc; 934 } 935 ARMRelocator::Address GOT_S = helper_GOT(pReloc, pParent); 936 ARMRelocator::DWord A = pReloc.target() + pReloc.addend(); 937 ARMRelocator::Address P = pReloc.place(); 938 939 // Apply relocation. 940 pReloc.target() = GOT_S + A - P; 941 return ARMRelocator::OK; 942 } 943 944 // R_ARM_THM_JUMP11: S + A - P 945 ARMRelocator::Result thm_jump11(Relocation& pReloc, ARMRelocator& pParent) 946 { 947 ARMRelocator::DWord P = pReloc.place(); 948 ARMRelocator::DWord A = 949 helper_sign_extend((pReloc.target() & 0x07ff) << 1, 11) + 950 pReloc.addend(); 951 // S depends on PLT exists or not 952 ARMRelocator::Address S = pReloc.symValue(); 953 if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) 954 S = helper_PLT(pReloc, pParent); 955 956 ARMRelocator::DWord X = S + A - P; 957 if (helper_check_signed_overflow(X, 11)) 958 return ARMRelocator::Overflow; 959 // Make sure the Imm is 0. Result Mask. 960 pReloc.target() = (pReloc.target() & 0xFFFFF800u) | ((X & 0x0FFEu) >> 1); 961 return ARMRelocator::OK; 962 } 963 964 // R_ARM_PC24: ((S + A) | T) - P 965 // R_ARM_PLT32: ((S + A) | T) - P 966 // R_ARM_JUMP24: ((S + A) | T) - P 967 // R_ARM_CALL: ((S + A) | T) - P 968 ARMRelocator::Result call(Relocation& pReloc, ARMRelocator& pParent) 969 { 970 // If target is undefined weak symbol, we only need to jump to the 971 // next instruction unless it has PLT entry. Rewrite instruction 972 // to NOP. 973 if (pReloc.symInfo()->isWeak() && 974 pReloc.symInfo()->isUndef() && 975 !pReloc.symInfo()->isDyn() && 976 !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) { 977 // change target to NOP : mov r0, r0 978 pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000; 979 return ARMRelocator::OK; 980 } 981 982 ARMRelocator::DWord T = getThumbBit(pReloc); 983 ARMRelocator::DWord A = 984 helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26) + 985 pReloc.addend(); 986 ARMRelocator::Address P = pReloc.place(); 987 ARMRelocator::Address S = pReloc.symValue(); 988 if (T != 0x0) 989 helper_clear_thumb_bit(S); 990 991 // S depends on PLT exists or not 992 if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 993 S = helper_PLT(pReloc, pParent); 994 T = 0; // PLT is not thumb. 995 } 996 997 // At this moment (after relaxation), if the jump target is thumb instruction, 998 // switch mode is needed, rewrite the instruction to BLX 999 // FIXME: check if we can use BLX instruction (check from .ARM.attribute 1000 // CPU ARCH TAG, which should be ARMv5 or above) 1001 if (T != 0) { 1002 // cannot rewrite to blx for R_ARM_JUMP24 1003 if (pReloc.type() == llvm::ELF::R_ARM_JUMP24) 1004 return ARMRelocator::BadReloc; 1005 if (pReloc.type() == llvm::ELF::R_ARM_PC24) 1006 return ARMRelocator::BadReloc; 1007 1008 pReloc.target() = (pReloc.target() & 0xffffff) | 1009 0xfa000000 | 1010 (((S + A - P) & 2) << 23); 1011 } 1012 1013 ARMRelocator::DWord X = ((S + A) | T) - P; 1014 // Check X is 24bit sign int. If not, we should use stub or PLT before apply. 1015 if (helper_check_signed_overflow(X, 26)) 1016 return ARMRelocator::Overflow; 1017 // Make sure the Imm is 0. Result Mask. 1018 pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2); 1019 return ARMRelocator::OK; 1020 } 1021 1022 // R_ARM_THM_CALL: ((S + A) | T) - P 1023 // R_ARM_THM_JUMP24: ((S + A) | T) - P 1024 ARMRelocator::Result thm_call(Relocation& pReloc, ARMRelocator& pParent) 1025 { 1026 // If target is undefined weak symbol, we only need to jump to the 1027 // next instruction unless it has PLT entry. Rewrite instruction 1028 // to NOP. 1029 if (pReloc.symInfo()->isWeak() && 1030 pReloc.symInfo()->isUndef() && 1031 !pReloc.symInfo()->isDyn() && 1032 !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) { 1033 pReloc.target() = (0xe000U << 16) | 0xbf00U; 1034 return ARMRelocator::OK; 1035 } 1036 1037 // get lower and upper 16 bit instructions from relocation targetData 1038 uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 1039 uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1040 1041 ARMRelocator::DWord T = getThumbBit(pReloc); 1042 ARMRelocator::DWord A = helper_thumb32_branch_offset(upper_inst, 1043 lower_inst); 1044 ARMRelocator::Address P = pReloc.place(); 1045 ARMRelocator::Address S; 1046 1047 // if symbol has plt 1048 if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 1049 S = helper_PLT(pReloc, pParent); 1050 T = 0; // PLT is not thumb. 1051 } 1052 else { 1053 S = pReloc.symValue(); 1054 if (T != 0x0) 1055 helper_clear_thumb_bit(S); 1056 } 1057 1058 S = S + A; 1059 1060 // At this moment (after relaxation), if the jump target is arm 1061 // instruction, switch mode is needed, rewrite the instruction to BLX 1062 // FIXME: check if we can use BLX instruction (check from .ARM.attribute 1063 // CPU ARCH TAG, which should be ARMv5 or above) 1064 if (T == 0) { 1065 // cannot rewrite to blx for R_ARM_THM_JUMP24 1066 if (pReloc.type() == llvm::ELF::R_ARM_THM_JUMP24) 1067 return ARMRelocator::BadReloc; 1068 1069 // for BLX, select bit 1 from relocation base address to jump target 1070 // address 1071 S = helper_bit_select(S, P, 0x2); 1072 // rewrite instruction to BLX 1073 lower_inst &= ~0x1000U; 1074 } 1075 else { 1076 // otherwise, the instruction should be BL 1077 lower_inst |= 0x1000U; 1078 } 1079 1080 ARMRelocator::DWord X = (S | T) - P; 1081 1082 // FIXME: Check bit size is 24(thumb2) or 22? 1083 if (helper_check_signed_overflow(X, 25)) { 1084 return ARMRelocator::Overflow; 1085 } 1086 1087 upper_inst = helper_thumb32_branch_upper(upper_inst, X); 1088 lower_inst = helper_thumb32_branch_lower(lower_inst, X); 1089 1090 *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst; 1091 *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst; 1092 1093 return ARMRelocator::OK; 1094 } 1095 1096 // R_ARM_MOVW_ABS_NC: (S + A) | T 1097 ARMRelocator::Result movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent) 1098 { 1099 ResolveInfo* rsym = pReloc.symInfo(); 1100 ARMRelocator::Address S = pReloc.symValue(); 1101 ARMRelocator::DWord T = getThumbBit(pReloc); 1102 ARMRelocator::DWord A = 1103 helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 1104 if (T != 0x0) 1105 helper_clear_thumb_bit(S); 1106 1107 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1108 1109 // If the flag of target section is not ALLOC, we will not scan this 1110 // relocation but perform static relocation. (e.g., applying .debug section) 1111 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1112 // use plt 1113 if (rsym->reserved() & ARMRelocator::ReservePLT) { 1114 S = helper_PLT(pReloc, pParent); 1115 T = 0 ; // PLT is not thumb 1116 } 1117 } 1118 1119 // perform static relocation 1120 ARMRelocator::DWord X = (S + A) | T; 1121 pReloc.target() = helper_insert_val_movw_movt_inst( 1122 pReloc.target() + pReloc.addend(), X); 1123 return ARMRelocator::OK; 1124 } 1125 1126 // R_ARM_MOVW_PREL_NC: ((S + A) | T) - P 1127 ARMRelocator::Result movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent) 1128 { 1129 ARMRelocator::Address S = pReloc.symValue(); 1130 ARMRelocator::DWord T = getThumbBit(pReloc); 1131 ARMRelocator::DWord P = pReloc.place(); 1132 ARMRelocator::DWord A = 1133 helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 1134 if (T != 0x0) 1135 helper_clear_thumb_bit(S); 1136 ARMRelocator::DWord X = ((S + A) | T) - P; 1137 1138 if (helper_check_signed_overflow(X, 16)) { 1139 return ARMRelocator::Overflow; 1140 } else { 1141 pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 1142 return ARMRelocator::OK; 1143 } 1144 } 1145 1146 // R_ARM_MOVT_ABS: S + A 1147 ARMRelocator::Result movt_abs(Relocation& pReloc, ARMRelocator& pParent) 1148 { 1149 ResolveInfo* rsym = pReloc.symInfo(); 1150 ARMRelocator::Address S = pReloc.symValue(); 1151 ARMRelocator::DWord A = 1152 helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 1153 1154 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1155 1156 // If the flag of target section is not ALLOC, we will not scan this relocation 1157 // but perform static relocation. (e.g., applying .debug section) 1158 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1159 // use plt 1160 if (rsym->reserved() & ARMRelocator::ReservePLT) { 1161 S = helper_PLT(pReloc, pParent); 1162 } 1163 } 1164 1165 ARMRelocator::DWord X = S + A; 1166 X >>= 16; 1167 // perform static relocation 1168 pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 1169 return ARMRelocator::OK; 1170 } 1171 1172 // R_ARM_MOVT_PREL: S + A - P 1173 ARMRelocator::Result movt_prel(Relocation& pReloc, ARMRelocator& pParent) 1174 { 1175 ARMRelocator::Address S = pReloc.symValue(); 1176 ARMRelocator::DWord P = pReloc.place(); 1177 ARMRelocator::DWord A = 1178 helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend(); 1179 ARMRelocator::DWord X = S + A - P; 1180 X >>= 16; 1181 1182 pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X); 1183 return ARMRelocator::OK; 1184 } 1185 1186 // R_ARM_THM_MOVW_ABS_NC: (S + A) | T 1187 ARMRelocator::Result thm_movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent) 1188 { 1189 ResolveInfo* rsym = pReloc.symInfo(); 1190 ARMRelocator::Address S = pReloc.symValue(); 1191 ARMRelocator::DWord T = getThumbBit(pReloc); 1192 if (T != 0x0) 1193 helper_clear_thumb_bit(S); 1194 1195 // get lower and upper 16 bit instructions from relocation targetData 1196 uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 1197 uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1198 ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1199 ARMRelocator::DWord A = 1200 helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 1201 1202 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1203 // If the flag of target section is not ALLOC, we will not scan this relocation 1204 // but perform static relocation. (e.g., applying .debug section) 1205 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1206 // use plt 1207 if (rsym->reserved() & ARMRelocator::ReservePLT) { 1208 S = helper_PLT(pReloc, pParent); 1209 T = 0; // PLT is not thumb 1210 } 1211 } 1212 ARMRelocator::DWord X = (S + A) | T; 1213 1214 val = helper_insert_val_thumb_movw_movt_inst(val, X); 1215 *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1216 *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 1217 1218 return ARMRelocator::OK; 1219 } 1220 1221 // R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P 1222 ARMRelocator::Result thm_movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent) 1223 { 1224 ARMRelocator::Address S = pReloc.symValue(); 1225 ARMRelocator::DWord T = getThumbBit(pReloc); 1226 ARMRelocator::DWord P = pReloc.place(); 1227 if (T != 0x0) 1228 helper_clear_thumb_bit(S); 1229 1230 // get lower and upper 16 bit instructions from relocation targetData 1231 uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 1232 uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1233 ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1234 ARMRelocator::DWord A = 1235 helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 1236 ARMRelocator::DWord X = ((S + A) | T) - P; 1237 1238 val = helper_insert_val_thumb_movw_movt_inst(val, X); 1239 *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1240 *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 1241 1242 return ARMRelocator::OK; 1243 } 1244 1245 // R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S) 1246 // R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S) 1247 ARMRelocator::Result thm_movw_brel(Relocation& pReloc, ARMRelocator& pParent) 1248 { 1249 ARMRelocator::Address S = pReloc.symValue(); 1250 ARMRelocator::DWord T = getThumbBit(pReloc); 1251 ARMRelocator::DWord P = pReloc.place(); 1252 if (T != 0x0) 1253 helper_clear_thumb_bit(S); 1254 1255 // get lower and upper 16 bit instructions from relocation targetData 1256 uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 1257 uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1258 ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1259 ARMRelocator::DWord A = 1260 helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 1261 1262 ARMRelocator::DWord X = ((S + A) | T) - P; 1263 1264 val = helper_insert_val_thumb_movw_movt_inst(val, X); 1265 *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1266 *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 1267 1268 return ARMRelocator::OK; 1269 } 1270 1271 // R_ARM_THM_MOVT_ABS: S + A 1272 ARMRelocator::Result thm_movt_abs(Relocation& pReloc, ARMRelocator& pParent) 1273 { 1274 ResolveInfo* rsym = pReloc.symInfo(); 1275 ARMRelocator::Address S = pReloc.symValue(); 1276 1277 // get lower and upper 16 bit instructions from relocation targetData 1278 uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 1279 uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1280 ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1281 ARMRelocator::DWord A = 1282 helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 1283 1284 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 1285 // If the flag of target section is not ALLOC, we will not scan this 1286 // relocation but perform static relocation. (e.g., applying .debug section) 1287 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 1288 // use plt 1289 if (rsym->reserved() & ARMRelocator::ReservePLT) { 1290 S = helper_PLT(pReloc, pParent); 1291 } 1292 } 1293 1294 ARMRelocator::DWord X = S + A; 1295 X >>= 16; 1296 1297 // check 16-bit overflow 1298 if (helper_check_signed_overflow(X, 16)) 1299 return ARMRelocator::Overflow; 1300 val = helper_insert_val_thumb_movw_movt_inst(val, X); 1301 *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1302 *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 1303 return ARMRelocator::OK; 1304 1305 } 1306 1307 // R_ARM_THM_MOVT_PREL: S + A - P 1308 // R_ARM_THM_MOVT_BREL: S + A - B(S) 1309 ARMRelocator::Result thm_movt_prel(Relocation& pReloc, ARMRelocator& pParent) 1310 { 1311 ARMRelocator::Address S = pReloc.symValue(); 1312 ARMRelocator::DWord P = pReloc.place(); 1313 1314 // get lower and upper 16 bit instructions from relocation targetData 1315 uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target())); 1316 uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1); 1317 ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst); 1318 ARMRelocator::DWord A = 1319 helper_extract_thumb_movw_movt_addend(val) + pReloc.addend(); 1320 ARMRelocator::DWord X = S + A - P; 1321 X >>= 16; 1322 1323 val = helper_insert_val_thumb_movw_movt_inst(val, X); 1324 *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16; 1325 *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu; 1326 1327 return ARMRelocator::OK; 1328 } 1329 1330 // R_ARM_PREL31: ((S + A) | T) - P 1331 ARMRelocator::Result prel31(Relocation& pReloc, ARMRelocator& pParent) 1332 { 1333 ARMRelocator::DWord target = pReloc.target(); 1334 ARMRelocator::DWord T = getThumbBit(pReloc); 1335 ARMRelocator::DWord A = helper_sign_extend(target, 31) + pReloc.addend(); 1336 ARMRelocator::DWord P = pReloc.place(); 1337 ARMRelocator::Address S = pReloc.symValue(); 1338 if (T != 0x0) 1339 helper_clear_thumb_bit(S); 1340 1341 // if symbol has plt 1342 if ( pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) { 1343 S = helper_PLT(pReloc, pParent); 1344 T = 0; // PLT is not thumb. 1345 } 1346 1347 ARMRelocator::DWord X = ((S + A) | T) - P; 1348 pReloc.target() = helper_bit_select(target, X, 0x7fffffffU); 1349 if (helper_check_signed_overflow(X, 31)) 1350 return ARMRelocator::Overflow; 1351 return ARMRelocator::OK; 1352 } 1353 1354 // R_ARM_TLS_GD32: GOT(S) + A - P 1355 // R_ARM_TLS_IE32: GOT(S) + A - P 1356 // R_ARM_TLS_LE32: S + A - tp 1357 ARMRelocator::Result tls(Relocation& pReloc, ARMRelocator& pParent) 1358 { 1359 return ARMRelocator::Unsupport; 1360 } 1361 1362 ARMRelocator::Result unsupport(Relocation& pReloc, ARMRelocator& pParent) 1363 { 1364 return ARMRelocator::Unsupport; 1365 } 1366