1//===- HexagonRelocator.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 "HexagonRelocator.h" 10#include "HexagonRelocationFunctions.h" 11#include "HexagonEncodings.h" 12#include <llvm/ADT/Twine.h> 13#include <llvm/Support/DataTypes.h> 14#include <llvm/Support/ELF.h> 15 16#include <mcld/LD/ELFFileFormat.h> 17#include <mcld/LD/LDSymbol.h> 18#include <mcld/Support/MsgHandling.h> 19 20using namespace mcld; 21 22//===--------------------------------------------------------------------===// 23// Relocation Helper Functions 24//===--------------------------------------------------------------------===// 25/// helper_DynRel - Get an relocation entry in .rela.dyn 26static Relocation &helper_DynRel_init(ResolveInfo *pSym, 27 Fragment &pFrag, 28 uint64_t pOffset, 29 Relocator::Type pType, 30 HexagonRelocator &pParent) { 31 HexagonLDBackend &ld_backend = pParent.getTarget(); 32 Relocation &rela_entry = *ld_backend.getRelaDyn().create(); 33 rela_entry.setType(pType); 34 rela_entry.targetRef().assign(pFrag, pOffset); 35 if (pType == llvm::ELF::R_HEX_RELATIVE || NULL == pSym) 36 rela_entry.setSymInfo(0); 37 else 38 rela_entry.setSymInfo(pSym); 39 40 return rela_entry; 41} 42 43/// helper_use_relative_reloc - Check if symbol can use relocation 44/// R_HEX_RELATIVE 45static bool helper_use_relative_reloc(const ResolveInfo &pSym, 46 const HexagonRelocator &pFactory) { 47 // if symbol is dynamic or undefine or preemptible 48 if (pSym.isDyn() || pSym.isUndef() || 49 pFactory.getTarget().isSymbolPreemptible(pSym)) 50 return false; 51 return true; 52} 53 54static HexagonGOTEntry &helper_GOT_init(Relocation &pReloc, 55 bool pHasRel, 56 HexagonRelocator &pParent) { 57 // rsym - The relocation target symbol 58 ResolveInfo *rsym = pReloc.symInfo(); 59 HexagonLDBackend &ld_backend = pParent.getTarget(); 60 assert(NULL == pParent.getSymGOTMap().lookUp(*rsym)); 61 62 HexagonGOTEntry *got_entry = ld_backend.getGOT().create(); 63 pParent.getSymGOTMap().record(*rsym, *got_entry); 64 65 if (!pHasRel) { 66 // No corresponding dynamic relocation, initialize to the symbol value. 67 got_entry->setValue(HexagonRelocator::SymVal); 68 } 69 else { 70 // Initialize got_entry content and the corresponding dynamic relocation. 71 if (helper_use_relative_reloc(*rsym, pParent)) { 72 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_RELATIVE, 73 pParent); 74 got_entry->setValue(HexagonRelocator::SymVal); 75 } 76 else { 77 helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_GLOB_DAT, 78 pParent); 79 got_entry->setValue(0); 80 } 81 } 82 return *got_entry; 83} 84 85static Relocator::Address helper_get_GOT_address(ResolveInfo &pSym, 86 HexagonRelocator &pParent) { 87 HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(pSym); 88 assert(NULL != got_entry); 89 return pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 90} 91 92static PLTEntryBase &helper_PLT_init(Relocation &pReloc, 93 HexagonRelocator &pParent) { 94 // rsym - The relocation target symbol 95 ResolveInfo *rsym = pReloc.symInfo(); 96 HexagonLDBackend &ld_backend = pParent.getTarget(); 97 assert(NULL == pParent.getSymPLTMap().lookUp(*rsym)); 98 99 PLTEntryBase *plt_entry = ld_backend.getPLT().create(); 100 pParent.getSymPLTMap().record(*rsym, *plt_entry); 101 102 assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) && 103 "PLT entry not exist, but DynRel entry exist!"); 104 HexagonGOTEntry *gotplt_entry = ld_backend.getGOTPLT().create(); 105 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 106 // init the corresponding rel entry in .rela.plt 107 Relocation &rela_entry = *ld_backend.getRelaPLT().create(); 108 rela_entry.setType(llvm::ELF::R_HEX_JMP_SLOT); 109 rela_entry.targetRef().assign(*gotplt_entry); 110 rela_entry.setSymInfo(rsym); 111 112 return *plt_entry; 113} 114 115static Relocator::Address helper_get_PLT_address(ResolveInfo& pSym, 116 HexagonRelocator &pParent) { 117 PLTEntryBase *plt_entry = pParent.getSymPLTMap().lookUp(pSym); 118 assert(NULL != plt_entry); 119 return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 120} 121 122//===--------------------------------------------------------------------===// 123// Relocation Functions and Tables 124//===--------------------------------------------------------------------===// 125DECL_HEXAGON_APPLY_RELOC_FUNCS 126 127/// the prototype of applying function 128typedef Relocator::Result (*ApplyFunctionType)(Relocation &pReloc, 129 HexagonRelocator &pParent); 130 131// the table entry of applying functions 132struct ApplyFunctionTriple { 133 ApplyFunctionType func; 134 unsigned int type; 135 const char *name; 136}; 137 138// declare the table of applying functions 139static const ApplyFunctionTriple ApplyFunctions[] = { 140 DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS 141}; 142 143static uint32_t findBitMask(uint32_t insn, Instruction *encodings, 144 int32_t numInsns) { 145 for (int32_t i = 0; i < numInsns; i++) { 146 if (((insn & 0xc000) == 0) && !(encodings[i].isDuplex)) 147 continue; 148 149 if (((insn & 0xc000) != 0) && (encodings[i].isDuplex)) 150 continue; 151 152 if (((encodings[i].insnMask) & insn) == encodings[i].insnCmpMask) 153 return encodings[i].insnBitMask; 154 } 155 assert(0); 156 // Should not be here, but add a return for -Werror=return-type 157 // error: control reaches end of non-void function 158 return -1; 159} 160 161#define FINDBITMASK(INSN) \ 162 findBitMask((uint32_t) INSN, insn_encodings, \ 163 sizeof(insn_encodings) / sizeof(Instruction)) 164 165//===--------------------------------------------------------------------===// 166// HexagonRelocator 167//===--------------------------------------------------------------------===// 168HexagonRelocator::HexagonRelocator(HexagonLDBackend &pParent, 169 const LinkerConfig &pConfig) 170 : Relocator(pConfig), m_Target(pParent) {} 171 172HexagonRelocator::~HexagonRelocator() {} 173 174Relocator::Result HexagonRelocator::applyRelocation(Relocation &pRelocation) { 175 Relocation::Type type = pRelocation.type(); 176 177 if (type > 85) { // 86-255 relocs do not exists for Hexagon 178 return Relocator::Unknown; 179 } 180 181 // apply the relocation 182 return ApplyFunctions[type].func(pRelocation, *this); 183} 184 185const char *HexagonRelocator::getName(Relocation::Type pType) const { 186 return ApplyFunctions[pType].name; 187} 188 189Relocator::Size HexagonRelocator::getSize(Relocation::Type pType) const { 190 return 32; 191} 192 193void HexagonRelocator::scanRelocation(Relocation &pReloc, IRBuilder &pLinker, 194 Module &pModule, LDSection &pSection, Input &pInput) { 195 if (LinkerConfig::Object == config().codeGenType()) 196 return; 197 198 // rsym - The relocation target symbol 199 ResolveInfo *rsym = pReloc.symInfo(); 200 assert(NULL != rsym && 201 "ResolveInfo of relocation not set while scanRelocation"); 202 203 if (config().isCodeStatic()) 204 return; 205 206 assert(NULL != pSection.getLink()); 207 if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 208 return; 209 210 if (rsym->isLocal()) // rsym is local 211 scanLocalReloc(pReloc, pLinker, pModule, pSection); 212 else // rsym is external 213 scanGlobalReloc(pReloc, pLinker, pModule, pSection); 214 215 // check if we should issue undefined reference for the relocation target 216 // symbol 217 if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 218 issueUndefRef(pReloc, pSection, pInput); 219} 220 221void HexagonRelocator::addCopyReloc(ResolveInfo &pSym, 222 HexagonLDBackend &pTarget) { 223 Relocation &rel_entry = *pTarget.getRelaDyn().create(); 224 rel_entry.setType(pTarget.getCopyRelType()); 225 assert(pSym.outSymbol()->hasFragRef()); 226 rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 227 rel_entry.setSymInfo(&pSym); 228} 229 230void HexagonRelocator::scanLocalReloc(Relocation &pReloc, IRBuilder &pBuilder, 231 Module &pModule, LDSection &pSection) { 232 // rsym - The relocation target symbol 233 ResolveInfo *rsym = pReloc.symInfo(); 234 235 switch (pReloc.type()) { 236 237 case llvm::ELF::R_HEX_LO16: 238 case llvm::ELF::R_HEX_HI16: 239 case llvm::ELF::R_HEX_16: 240 case llvm::ELF::R_HEX_8: 241 case llvm::ELF::R_HEX_32_6_X: 242 case llvm::ELF::R_HEX_16_X: 243 case llvm::ELF::R_HEX_12_X: 244 case llvm::ELF::R_HEX_11_X: 245 case llvm::ELF::R_HEX_10_X: 246 case llvm::ELF::R_HEX_9_X: 247 case llvm::ELF::R_HEX_8_X: 248 case llvm::ELF::R_HEX_7_X: 249 case llvm::ELF::R_HEX_6_X: 250 assert(!(rsym->reserved() & ReserveRel) && 251 "Cannot apply this relocation for read only section"); 252 return; 253 254 case llvm::ELF::R_HEX_32: 255 // If buiding PIC object (shared library or PIC executable), 256 // a dynamic relocations with RELATIVE type to this location is needed. 257 // Reserve an entry in .rel.dyn 258 if (config().isCodeIndep()) { 259 Relocation &reloc = helper_DynRel_init(rsym, 260 *pReloc.targetRef().frag(), 261 pReloc.targetRef().offset(), 262 llvm::ELF::R_HEX_RELATIVE, 263 *this); 264 // we need to set up the relocation addend at apply relocation, record the 265 // relocation 266 getRelRelMap().record(pReloc, reloc); 267 268 // set Rel bit 269 rsym->setReserved(rsym->reserved() | ReserveRel); 270 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 271 } 272 return; 273 274 default: 275 return; 276 } 277} 278 279void HexagonRelocator::scanGlobalReloc(Relocation &pReloc, IRBuilder &pBuilder, 280 Module &pModule, LDSection &pSection) { 281 // rsym - The relocation target symbol 282 ResolveInfo *rsym = pReloc.symInfo(); 283 HexagonLDBackend &ld_backend = getTarget(); 284 285 switch (pReloc.type()) { 286 case llvm::ELF::R_HEX_LO16: 287 case llvm::ELF::R_HEX_HI16: 288 case llvm::ELF::R_HEX_16: 289 case llvm::ELF::R_HEX_8: 290 case llvm::ELF::R_HEX_32_6_X: 291 case llvm::ELF::R_HEX_16_X: 292 case llvm::ELF::R_HEX_12_X: 293 case llvm::ELF::R_HEX_11_X: 294 case llvm::ELF::R_HEX_10_X: 295 case llvm::ELF::R_HEX_9_X: 296 case llvm::ELF::R_HEX_8_X: 297 case llvm::ELF::R_HEX_7_X: 298 case llvm::ELF::R_HEX_6_X: 299 assert(!(rsym->reserved() & ReserveRel) && 300 "Cannot apply this relocation for read only section"); 301 return; 302 303 case llvm::ELF::R_HEX_32: 304 if (ld_backend.symbolNeedsPLT(*rsym)) { 305 //create PLT for this symbol if it does not have. 306 if (!(rsym->reserved() & ReservePLT)) { 307 helper_PLT_init(pReloc, *this); 308 rsym->setReserved(rsym->reserved() | ReservePLT); 309 } 310 } 311 312 if (ld_backend.symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 313 true)) { 314 if (ld_backend.symbolNeedsCopyReloc(pReloc, *rsym)) { 315 LDSymbol &cpy_sym = 316 defineSymbolforCopyReloc(pBuilder, *rsym, ld_backend); 317 addCopyReloc(*cpy_sym.resolveInfo(), ld_backend); 318 } 319 else { 320 Relocation &reloc = helper_DynRel_init(rsym, 321 *pReloc.targetRef().frag(), 322 pReloc.targetRef().offset(), 323 llvm::ELF::R_HEX_RELATIVE, 324 *this); 325 // we need to set up the relocation addend at apply relocation, record the 326 // relocation 327 getRelRelMap().record(pReloc, reloc); 328 rsym->setReserved(rsym->reserved() | ReserveRel); 329 ld_backend.checkAndSetHasTextRel(*pSection.getLink()); 330 } 331 } 332 return; 333 334 case llvm::ELF::R_HEX_GOTREL_LO16: 335 case llvm::ELF::R_HEX_GOTREL_HI16: 336 case llvm::ELF::R_HEX_GOTREL_32: 337 case llvm::ELF::R_HEX_GOTREL_32_6_X: 338 case llvm::ELF::R_HEX_GOTREL_16_X: 339 case llvm::ELF::R_HEX_GOTREL_11_X: 340 // This assumes that GOT exists 341 return; 342 343 case llvm::ELF::R_HEX_GOT_LO16: 344 case llvm::ELF::R_HEX_GOT_HI16: 345 case llvm::ELF::R_HEX_GOT_32: 346 case llvm::ELF::R_HEX_GOT_16: 347 case llvm::ELF::R_HEX_GOT_32_6_X: 348 case llvm::ELF::R_HEX_GOT_16_X: 349 case llvm::ELF::R_HEX_GOT_11_X: 350 // Symbol needs GOT entry, reserve entry in .got 351 // return if we already create GOT for this symbol 352 if (rsym->reserved() & ReserveGOT) 353 return; 354 // If the GOT is used in statically linked binaries, 355 // the GOT entry is enough and no relocation is needed. 356 if (config().isCodeStatic()) 357 helper_GOT_init(pReloc, false, *this); 358 else 359 helper_GOT_init(pReloc, true, *this); 360 // set GOT bit 361 rsym->setReserved(rsym->reserved() | ReserveGOT); 362 return; 363 364 case llvm::ELF::R_HEX_B22_PCREL: 365 case llvm::ELF::R_HEX_B15_PCREL: 366 case llvm::ELF::R_HEX_B7_PCREL: 367 case llvm::ELF::R_HEX_B13_PCREL: 368 case llvm::ELF::R_HEX_B9_PCREL: 369 case llvm::ELF::R_HEX_B32_PCREL_X: 370 case llvm::ELF::R_HEX_B22_PCREL_X: 371 case llvm::ELF::R_HEX_B15_PCREL_X: 372 case llvm::ELF::R_HEX_B13_PCREL_X: 373 case llvm::ELF::R_HEX_B9_PCREL_X: 374 case llvm::ELF::R_HEX_B7_PCREL_X: 375 case llvm::ELF::R_HEX_32_PCREL: 376 case llvm::ELF::R_HEX_6_PCREL_X: 377 case llvm::ELF::R_HEX_PLT_B22_PCREL: 378 if (rsym->reserved() & ReservePLT) 379 return; 380 if (ld_backend.symbolNeedsPLT(*rsym) || 381 pReloc.type() == llvm::ELF::R_HEX_PLT_B22_PCREL) { 382 helper_PLT_init(pReloc, *this); 383 rsym->setReserved(rsym->reserved() | ReservePLT); 384 } 385 return; 386 387 default: 388 break; 389 390 } // end of switch 391} 392 393/// defineSymbolforCopyReloc 394/// For a symbol needing copy relocation, define a copy symbol in the BSS 395/// section and all other reference to this symbol should refer to this 396/// copy. 397/// @note This is executed at `scan relocation' stage. 398LDSymbol &HexagonRelocator::defineSymbolforCopyReloc( 399 IRBuilder &pBuilder, const ResolveInfo &pSym, HexagonLDBackend &pTarget) { 400 // get or create corresponding BSS LDSection 401 LDSection *bss_sect_hdr = NULL; 402 ELFFileFormat *file_format = pTarget.getOutputFormat(); 403 if (ResolveInfo::ThreadLocal == pSym.type()) 404 bss_sect_hdr = &file_format->getTBSS(); 405 else 406 bss_sect_hdr = &file_format->getBSS(); 407 408 // get or create corresponding BSS SectionData 409 assert(NULL != bss_sect_hdr); 410 SectionData *bss_section = NULL; 411 if (bss_sect_hdr->hasSectionData()) 412 bss_section = bss_sect_hdr->getSectionData(); 413 else 414 bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr); 415 416 // Determine the alignment by the symbol value 417 // FIXME: here we use the largest alignment 418 uint32_t addralign = config().targets().bitclass() / 8; 419 420 // allocate space in BSS for the copy symbol 421 Fragment *frag = new FillFragment(0x0, 1, pSym.size()); 422 uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_section, addralign); 423 bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 424 425 // change symbol binding to Global if it's a weak symbol 426 ResolveInfo::Binding binding = (ResolveInfo::Binding) pSym.binding(); 427 if (binding == ResolveInfo::Weak) 428 binding = ResolveInfo::Global; 429 430 // Define the copy symbol in the bss section and resolve it 431 LDSymbol *cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 432 pSym.name(), (ResolveInfo::Type) pSym.type(), ResolveInfo::Define, 433 binding, pSym.size(), // size 434 0x0, // value 435 FragmentRef::Create(*frag, 0x0), (ResolveInfo::Visibility) pSym.other()); 436 437 // output all other alias symbols if any 438 Module &pModule = pBuilder.getModule(); 439 Module::AliasList *alias_list = pModule.getAliasList(pSym); 440 if (NULL != alias_list) { 441 Module::alias_iterator it, it_e = alias_list->end(); 442 for (it = alias_list->begin(); it != it_e; ++it) { 443 const ResolveInfo *alias = *it; 444 if (alias != &pSym && alias->isDyn()) { 445 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 446 alias->name(), (ResolveInfo::Type) alias->type(), 447 ResolveInfo::Define, binding, alias->size(), // size 448 0x0, // value 449 FragmentRef::Create(*frag, 0x0), 450 (ResolveInfo::Visibility) alias->other()); 451 } 452 } 453 } 454 455 return *cpy_sym; 456} 457 458void HexagonRelocator::partialScanRelocation(Relocation &pReloc, 459 Module &pModule, 460 const LDSection &pSection) { 461 pReloc.updateAddend(); 462 // if we meet a section symbol 463 if (pReloc.symInfo()->type() == ResolveInfo::Section) { 464 LDSymbol *input_sym = pReloc.symInfo()->outSymbol(); 465 466 // 1. update the relocation target offset 467 assert(input_sym->hasFragRef()); 468 // 2. get the output LDSection which the symbol defined in 469 const LDSection &out_sect = 470 input_sym->fragRef()->frag()->getParent()->getSection(); 471 ResolveInfo *sym_info = 472 pModule.getSectionSymbolSet().get(out_sect)->resolveInfo(); 473 // set relocation target symbol to the output section symbol's resolveInfo 474 pReloc.setSymInfo(sym_info); 475 } 476} 477 478//=========================================// 479// Each relocation function implementation // 480//=========================================// 481 482// R_HEX_NONE 483Relocator::Result none(Relocation &pReloc, HexagonRelocator &pParent) { 484 return Relocator::OK; 485} 486 487//R_HEX_32 and its class of relocations use only addend and symbol value 488// S + A : result is unsigned truncate. 489// Exception: R_HEX_32_6_X : unsigned verify 490Relocator::Result applyAbs(Relocation &pReloc) { 491 Relocator::Address S = pReloc.symValue(); 492 Relocator::DWord A = pReloc.addend(); 493 uint32_t result = (uint32_t)(S + A); 494 uint32_t bitMask = 0; 495 uint32_t effectiveBits = 0; 496 uint32_t alignment = 1; 497 uint32_t shift = 0; 498 499 switch (pReloc.type()) { 500 case llvm::ELF::R_HEX_LO16: 501 bitMask = 0x00c03fff; 502 break; 503 504 case llvm::ELF::R_HEX_HI16: 505 shift = 16; 506 bitMask = 0x00c03fff; 507 break; 508 509 case llvm::ELF::R_HEX_32: 510 bitMask = 0xffffffff; 511 break; 512 513 case llvm::ELF::R_HEX_16: 514 bitMask = 0x0000ffff; 515 alignment = 2; 516 break; 517 518 case llvm::ELF::R_HEX_8: 519 bitMask = 0x000000ff; 520 alignment = 1; 521 break; 522 523 case llvm::ELF::R_HEX_12_X: 524 bitMask = 0x000007e0; 525 break; 526 527 case llvm::ELF::R_HEX_32_6_X: 528 bitMask = 0xfff3fff; 529 shift = 6; 530 effectiveBits = 26; 531 break; 532 533 case llvm::ELF::R_HEX_16_X: 534 case llvm::ELF::R_HEX_11_X: 535 case llvm::ELF::R_HEX_10_X: 536 case llvm::ELF::R_HEX_9_X: 537 case llvm::ELF::R_HEX_8_X: 538 case llvm::ELF::R_HEX_7_X: 539 case llvm::ELF::R_HEX_6_X: 540 bitMask = FINDBITMASK(pReloc.target()); 541 break; 542 543 default: 544 // show proper error 545 fatal(diag::unsupported_relocation) << (int) 546 pReloc.type() << "mclinker@googlegroups.com"; 547 548 } 549 550 if ((shift != 0) && (result % alignment != 0)) 551 return Relocator::BadReloc; 552 553 result >>= shift; 554 555 if (effectiveBits) { 556 uint32_t range = 1 << effectiveBits; 557 if (result > (range - 1)) 558 return Relocator::Overflow; 559 } 560 561 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result); 562 return Relocator::OK; 563} 564 565//R_HEX_B22_PCREL and its class of relocations, use 566// S + A - P : result is signed verify. 567// Exception: R_HEX_B32_PCREL_X : signed truncate 568// Another Exception: R_HEX_6_PCREL_X is unsigned truncate 569Relocator::Result applyRel(Relocation &pReloc, int64_t pResult) { 570 uint32_t bitMask = 0; 571 uint32_t effectiveBits = 0; 572 uint32_t alignment = 1; 573 uint32_t result; 574 uint32_t shift = 0; 575 576 switch (pReloc.type()) { 577 case llvm::ELF::R_HEX_B22_PCREL: 578 bitMask = 0x01ff3ffe; 579 effectiveBits = 22; 580 alignment = 4; 581 shift = 2; 582 break; 583 584 case llvm::ELF::R_HEX_B15_PCREL: 585 bitMask = 0x00df20fe; 586 effectiveBits = 15; 587 alignment = 4; 588 shift = 2; 589 break; 590 591 case llvm::ELF::R_HEX_B7_PCREL: 592 bitMask = 0x00001f18; 593 effectiveBits = 7; 594 alignment = 4; 595 shift = 2; 596 break; 597 598 case llvm::ELF::R_HEX_B13_PCREL: 599 bitMask = 0x00202ffe; 600 effectiveBits = 13; 601 alignment = 4; 602 shift = 2; 603 break; 604 605 case llvm::ELF::R_HEX_B9_PCREL: 606 bitMask = 0x003000fe; 607 effectiveBits = 9; 608 alignment = 4; 609 shift = 2; 610 break; 611 612 case llvm::ELF::R_HEX_B32_PCREL_X: 613 bitMask = 0xfff3fff; 614 shift = 6; 615 break; 616 617 case llvm::ELF::R_HEX_B22_PCREL_X: 618 bitMask = 0x01ff3ffe; 619 effectiveBits = 22; 620 pResult &= 0x3f; 621 break; 622 623 case llvm::ELF::R_HEX_B15_PCREL_X: 624 bitMask = 0x00df20fe; 625 effectiveBits = 15; 626 pResult &= 0x3f; 627 break; 628 629 case llvm::ELF::R_HEX_B13_PCREL_X: 630 bitMask = 0x00202ffe; 631 effectiveBits = 13; 632 pResult &= 0x3f; 633 break; 634 635 case llvm::ELF::R_HEX_B9_PCREL_X: 636 bitMask = 0x003000fe; 637 effectiveBits = 9; 638 pResult &= 0x3f; 639 break; 640 641 case llvm::ELF::R_HEX_B7_PCREL_X: 642 bitMask = 0x00001f18; 643 effectiveBits = 7; 644 pResult &= 0x3f; 645 break; 646 647 case llvm::ELF::R_HEX_32_PCREL: 648 bitMask = 0xffffffff; 649 effectiveBits = 32; 650 break; 651 652 case llvm::ELF::R_HEX_6_PCREL_X: 653 // This is unique since it has a unsigned operand and its truncated 654 bitMask = FINDBITMASK(pReloc.target()); 655 result = pReloc.addend() + pReloc.symValue() - pReloc.place(); 656 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result); 657 return Relocator::OK; 658 659 default: 660 // show proper error 661 fatal(diag::unsupported_relocation) << (int) 662 pReloc.type() << "mclinker@googlegroups.com"; 663 } 664 665 if ((shift != 0) && (pResult % alignment != 0)) 666 return Relocator::BadReloc; 667 668 pResult >>= shift; 669 670 if (effectiveBits) { 671 int64_t range = 1LL << (effectiveBits - 1); 672 if ((pResult > (range - 1)) || (pResult < -range)) 673 return Relocator::Overflow; 674 } 675 676 pReloc.target() |= (uint32_t) ApplyMask<int32_t>(bitMask, pResult); 677 return Relocator::OK; 678} 679 680Relocator::Result relocAbs(Relocation &pReloc, HexagonRelocator &pParent) { 681 ResolveInfo *rsym = pReloc.symInfo(); 682 Relocator::Address S = pReloc.symValue(); 683 Relocator::DWord A = pReloc.addend(); 684 685 Relocation* rel_entry = pParent.getRelRelMap().lookUp(pReloc); 686 bool has_dyn_rel = (NULL != rel_entry); 687 688 // if the flag of target section is not ALLOC, we eprform only static 689 // relocation. 690 if (0 == (llvm::ELF::SHF_ALLOC & 691 pReloc.targetRef().frag()->getParent()->getSection().flag())) { 692 return applyAbs(pReloc); 693 } 694 695 // a local symbol with .rela type relocation 696 if (rsym->isLocal() && has_dyn_rel) { 697 rel_entry->setAddend(S + A); 698 return Relocator::OK; 699 } 700 701 if (!rsym->isLocal()) { 702 if (rsym->reserved() & HexagonRelocator::ReservePLT) { 703 S = helper_get_PLT_address(*rsym, pParent); 704 } 705 706 if (has_dyn_rel) { 707 if (llvm::ELF::R_HEX_32 == pReloc.type() && 708 helper_use_relative_reloc(*rsym, pParent)) { 709 rel_entry->setAddend(S + A); 710 } else { 711 rel_entry->setAddend(A); 712 return Relocator::OK; 713 } 714 } 715 } 716 717 return applyAbs(pReloc); 718} 719 720Relocator::Result relocPCREL(Relocation &pReloc, HexagonRelocator &pParent) { 721 ResolveInfo *rsym = pReloc.symInfo(); 722 int64_t result; 723 724 Relocator::Address S = pReloc.symValue(); 725 Relocator::DWord A = pReloc.addend(); 726 Relocator::DWord P = pReloc.place(); 727 728 FragmentRef &target_fragref = pReloc.targetRef(); 729 Fragment *target_frag = target_fragref.frag(); 730 LDSection &target_sect = target_frag->getParent()->getSection(); 731 732 result = (int64_t)(S + A - P); 733 734 // for relocs inside non ALLOC, just apply 735 if (0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 736 return applyRel(pReloc, result); 737 } 738 739 if (!rsym->isLocal()) { 740 if (rsym->reserved() & HexagonRelocator::ReservePLT) { 741 S = helper_get_PLT_address(*rsym, pParent); 742 result = (int64_t)(S + A - P); 743 applyRel(pReloc, result); 744 return Relocator::OK; 745 } 746 } 747 748 return applyRel(pReloc, result); 749} 750 751// R_HEX_GPREL16_0 and its class : Unsigned Verify 752Relocator::Result relocGPREL(Relocation &pReloc, HexagonRelocator &pParent) { 753 Relocator::Address S = pReloc.symValue(); 754 Relocator::DWord A = pReloc.addend(); 755 Relocator::DWord GP = pParent.getTarget().getGP(); 756 757 uint32_t result = (uint32_t)(S + A - GP); 758 uint32_t shift = 0; 759 uint32_t alignment = 1; 760 761 switch (pReloc.type()) { 762 case llvm::ELF::R_HEX_GPREL16_0: 763 break; 764 765 case llvm::ELF::R_HEX_GPREL16_1: 766 shift = 1; 767 alignment = 2; 768 break; 769 770 case llvm::ELF::R_HEX_GPREL16_2: 771 shift = 2; 772 alignment = 4; 773 break; 774 775 case llvm::ELF::R_HEX_GPREL16_3: 776 shift = 3; 777 alignment = 8; 778 break; 779 780 default: 781 // show proper error 782 fatal(diag::unsupported_relocation) << (int) 783 pReloc.type() << "mclinker@googlegroups.com"; 784 } 785 786 uint32_t range = 1 << 16; 787 uint32_t bitMask = FINDBITMASK(pReloc.target()); 788 789 if ((shift != 0) && (result % alignment != 0)) 790 return Relocator::BadReloc; 791 792 result >>= shift; 793 794 if (result < range - 1) { 795 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result); 796 return Relocator::OK; 797 } 798 return Relocator::Overflow; 799} 800 801// R_HEX_PLT_B22_PCREL: PLT(S) + A - P 802Relocator::Result relocPLTB22PCREL(Relocation &pReloc, 803 HexagonRelocator &pParent) { 804 // PLT_S depends on if there is a PLT entry. 805 Relocator::Address PLT_S; 806 if ((pReloc.symInfo()->reserved() & HexagonRelocator::ReservePLT)) 807 PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 808 else 809 PLT_S = pReloc.symValue(); 810 Relocator::Address P = pReloc.place(); 811 uint32_t bitMask = FINDBITMASK(pReloc.target()); 812 uint32_t result = (PLT_S + pReloc.addend() - P) >> 2; 813 pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result); 814 return Relocator::OK; 815} 816 817//R_HEX_GOT_LO16 and its class : (G) Signed Truncate 818//Exception: R_HEX_GOT_16(_X): signed verify 819// Exception: R_HEX_GOT_11_X : unsigned truncate 820Relocator::Result relocGOT(Relocation &pReloc, HexagonRelocator &pParent) { 821 if (!(pReloc.symInfo()->reserved() & HexagonRelocator::ReserveGOT)) { 822 return Relocator::BadReloc; 823 } 824 825 // set got entry value if needed 826 HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 827 assert(NULL != got_entry); 828 if (HexagonRelocator::SymVal == got_entry->getValue()) 829 got_entry->setValue(pReloc.symValue()); 830 831 Relocator::Address GOT_S = 832 helper_get_GOT_address(*pReloc.symInfo(), pParent); 833 Relocator::Address GOT = pParent.getTarget().getGOTSymbolAddr(); 834 int32_t result = (int32_t)(GOT_S - GOT); 835 uint32_t effectiveBits = 0; 836 uint32_t alignment = 1; 837 uint32_t bitMask = 0; 838 uint32_t result_u; 839 uint32_t shift = 0; 840 841 switch (pReloc.type()) { 842 case llvm::ELF::R_HEX_GOT_LO16: 843 bitMask = 0x00c03fff; 844 break; 845 846 case llvm::ELF::R_HEX_GOT_HI16: 847 bitMask = 0x00c03fff; 848 shift = 16; 849 alignment = 4; 850 break; 851 852 case llvm::ELF::R_HEX_GOT_32: 853 bitMask = 0xffffffff; 854 break; 855 856 case llvm::ELF::R_HEX_GOT_16: 857 bitMask = FINDBITMASK(pReloc.target()); 858 effectiveBits = 16; 859 break; 860 861 case llvm::ELF::R_HEX_GOT_32_6_X: 862 bitMask = 0xfff3fff; 863 shift = 6; 864 break; 865 866 case llvm::ELF::R_HEX_GOT_16_X: 867 bitMask = FINDBITMASK(pReloc.target()); 868 effectiveBits = 6; 869 break; 870 871 case llvm::ELF::R_HEX_GOT_11_X: 872 bitMask = FINDBITMASK(pReloc.target()); 873 result_u = GOT_S - GOT; 874 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result_u); 875 return Relocator::OK; 876 877 default: 878 // show proper error 879 fatal(diag::unsupported_relocation) << (int) 880 pReloc.type() << "mclinker@googlegroups.com"; 881 } 882 883 if ((shift != 0) && (result % alignment != 0)) 884 return Relocator::BadReloc; 885 886 result >>= shift; 887 888 if (effectiveBits) { 889 int32_t range = 1 << (effectiveBits - 1); 890 if ((result > range - 1) || (result < -range)) 891 return Relocator::Overflow; 892 } 893 pReloc.target() |= ApplyMask<int32_t>(bitMask, result); 894 return Relocator::OK; 895} 896 897// R_HEX_GOTREL_LO16: and its class of relocs 898// (S + A - GOT) : Signed Truncate 899Relocator::Result relocGOTREL(Relocation &pReloc, HexagonRelocator &pParent) { 900 Relocator::Address S = pReloc.symValue(); 901 Relocator::DWord A = pReloc.addend(); 902 Relocator::Address GOT = pParent.getTarget().getGOTSymbolAddr(); 903 904 uint32_t bitMask = 0; 905 uint32_t alignment = 1; 906 uint32_t shift = 0; 907 908 uint32_t result = (uint32_t)(S + A - GOT); 909 910 switch (pReloc.type()) { 911 case llvm::ELF::R_HEX_GOTREL_LO16: 912 bitMask = 0x00c03fff; 913 break; 914 915 case llvm::ELF::R_HEX_GOTREL_HI16: 916 bitMask = 0x00c03fff; 917 shift = 16; 918 alignment = 4; 919 break; 920 921 case llvm::ELF::R_HEX_GOTREL_32: 922 bitMask = 0xffffffff; 923 break; 924 925 case llvm::ELF::R_HEX_GOTREL_32_6_X: 926 bitMask = 0x0fff3fff; 927 shift = 6; 928 break; 929 930 case llvm::ELF::R_HEX_GOTREL_16_X: 931 case llvm::ELF::R_HEX_GOTREL_11_X: 932 bitMask = FINDBITMASK(pReloc.target()); 933 break; 934 935 default: 936 // show proper error 937 fatal(diag::unsupported_relocation) << (int) 938 pReloc.type() << "mclinker@googlegroups.com"; 939 } 940 941 if (result % alignment != 0) 942 return Relocator::BadReloc; 943 944 result >>= shift; 945 946 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result); 947 return Relocator::OK; 948} 949 950Relocator::Result unsupport(Relocation &pReloc, HexagonRelocator &pParent) { 951 return Relocator::Unsupport; 952} 953