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