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