HexagonRelocator.cpp revision 87f34658dec9097d987d254a990ea7f311bfc95f
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 HexagonRelocator::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 HexagonRelocator::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 HexagonRelocator::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 128 typedef 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 483HexagonRelocator::Result none(Relocation &pReloc, HexagonRelocator &pParent) { 484 return HexagonRelocator::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 490HexagonRelocator::Result applyAbs(Relocation &pReloc) { 491 HexagonRelocator::Address S = pReloc.symValue(); 492 HexagonRelocator::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 HexagonRelocator::BadReloc; 552 553 result >>= shift; 554 555 if (effectiveBits) { 556 uint32_t range = 1 << effectiveBits; 557 if (result > (range - 1)) 558 return HexagonRelocator::Overflow; 559 } 560 561 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result); 562 return HexagonRelocator::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 569HexagonRelocator::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 HexagonRelocator::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 HexagonRelocator::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 HexagonRelocator::Overflow; 674 } 675 676 pReloc.target() |= (uint32_t) ApplyMask<int32_t>(bitMask, pResult); 677 return HexagonRelocator::OK; 678} 679 680HexagonRelocator::Result relocAbs(Relocation &pReloc, 681 HexagonRelocator &pParent) { 682 ResolveInfo *rsym = pReloc.symInfo(); 683 HexagonRelocator::Address S = pReloc.symValue(); 684 HexagonRelocator::DWord A = pReloc.addend(); 685 686 Relocation* rel_entry = pParent.getRelRelMap().lookUp(pReloc); 687 bool has_dyn_rel = (NULL != rel_entry); 688 689 // if the flag of target section is not ALLOC, we eprform only static 690 // relocation. 691 if (0 == (llvm::ELF::SHF_ALLOC & 692 pReloc.targetRef().frag()->getParent()->getSection().flag())) { 693 return applyAbs(pReloc); 694 } 695 696 // a local symbol with .rela type relocation 697 if (rsym->isLocal() && has_dyn_rel) { 698 rel_entry->setAddend(S + A); 699 return HexagonRelocator::OK; 700 } 701 702 if (!rsym->isLocal()) { 703 if (rsym->reserved() & HexagonRelocator::ReservePLT) { 704 S = helper_get_PLT_address(*rsym, pParent); 705 } 706 707 if (has_dyn_rel) { 708 if (llvm::ELF::R_HEX_32 == pReloc.type() && 709 helper_use_relative_reloc(*rsym, pParent)) { 710 rel_entry->setAddend(S + A); 711 } else { 712 rel_entry->setAddend(A); 713 return HexagonRelocator::OK; 714 } 715 } 716 } 717 718 return applyAbs(pReloc); 719} 720 721HexagonRelocator::Result relocPCREL(Relocation &pReloc, 722 HexagonRelocator &pParent) { 723 ResolveInfo *rsym = pReloc.symInfo(); 724 int64_t result; 725 726 HexagonRelocator::Address S = pReloc.symValue(); 727 HexagonRelocator::DWord A = pReloc.addend(); 728 HexagonRelocator::DWord P = pReloc.place(); 729 730 FragmentRef &target_fragref = pReloc.targetRef(); 731 Fragment *target_frag = target_fragref.frag(); 732 LDSection &target_sect = target_frag->getParent()->getSection(); 733 734 result = (int64_t)(S + A - P); 735 736 // for relocs inside non ALLOC, just apply 737 if (0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 738 return applyRel(pReloc, result); 739 } 740 741 if (!rsym->isLocal()) { 742 if (rsym->reserved() & HexagonRelocator::ReservePLT) { 743 S = helper_get_PLT_address(*rsym, pParent); 744 result = (int64_t)(S + A - P); 745 applyRel(pReloc, result); 746 return HexagonRelocator::OK; 747 } 748 } 749 750 return applyRel(pReloc, result); 751} 752 753// R_HEX_GPREL16_0 and its class : Unsigned Verify 754HexagonRelocator::Result relocGPREL(Relocation &pReloc, 755 HexagonRelocator &pParent) { 756 HexagonRelocator::Address S = pReloc.symValue(); 757 HexagonRelocator::DWord A = pReloc.addend(); 758 HexagonRelocator::DWord GP = pParent.getTarget().getGP(); 759 760 uint32_t result = (uint32_t)(S + A - GP); 761 uint32_t shift = 0; 762 uint32_t alignment = 1; 763 764 switch (pReloc.type()) { 765 case llvm::ELF::R_HEX_GPREL16_0: 766 break; 767 768 case llvm::ELF::R_HEX_GPREL16_1: 769 shift = 1; 770 alignment = 2; 771 break; 772 773 case llvm::ELF::R_HEX_GPREL16_2: 774 shift = 2; 775 alignment = 4; 776 break; 777 778 case llvm::ELF::R_HEX_GPREL16_3: 779 shift = 3; 780 alignment = 8; 781 break; 782 783 default: 784 // show proper error 785 fatal(diag::unsupported_relocation) << (int) 786 pReloc.type() << "mclinker@googlegroups.com"; 787 } 788 789 uint32_t range = 1 << 16; 790 uint32_t bitMask = FINDBITMASK(pReloc.target()); 791 792 if ((shift != 0) && (result % alignment != 0)) 793 return HexagonRelocator::BadReloc; 794 795 result >>= shift; 796 797 if (result < range - 1) { 798 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result); 799 return HexagonRelocator::OK; 800 } 801 return HexagonRelocator::Overflow; 802} 803 804// R_HEX_PLT_B22_PCREL: PLT(S) + A - P 805HexagonRelocator::Result relocPLTB22PCREL(Relocation &pReloc, 806 HexagonRelocator &pParent) { 807 // PLT_S depends on if there is a PLT entry. 808 HexagonRelocator::Address PLT_S; 809 if ((pReloc.symInfo()->reserved() & HexagonRelocator::ReservePLT)) 810 PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 811 else 812 PLT_S = pReloc.symValue(); 813 HexagonRelocator::Address P = pReloc.place(); 814 uint32_t bitMask = FINDBITMASK(pReloc.target()); 815 uint32_t result = (PLT_S + pReloc.addend() - P) >> 2; 816 pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result); 817 return HexagonRelocator::OK; 818} 819 820//R_HEX_GOT_LO16 and its class : (G) Signed Truncate 821//Exception: R_HEX_GOT_16(_X): signed verify 822// Exception: R_HEX_GOT_11_X : unsigned truncate 823HexagonRelocator::Result relocGOT(Relocation &pReloc, 824 HexagonRelocator &pParent) { 825 if (!(pReloc.symInfo()->reserved() & HexagonRelocator::ReserveGOT)) { 826 return HexagonRelocator::BadReloc; 827 } 828 829 // set got entry value if needed 830 HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 831 assert(NULL != got_entry); 832 if (HexagonRelocator::SymVal == got_entry->getValue()) 833 got_entry->setValue(pReloc.symValue()); 834 835 HexagonRelocator::Address GOT_S = 836 helper_get_GOT_address(*pReloc.symInfo(), pParent); 837 HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr(); 838 int32_t result = (int32_t)(GOT_S - GOT); 839 uint32_t effectiveBits = 0; 840 uint32_t alignment = 1; 841 uint32_t bitMask = 0; 842 uint32_t result_u; 843 uint32_t shift = 0; 844 845 switch (pReloc.type()) { 846 case llvm::ELF::R_HEX_GOT_LO16: 847 bitMask = 0x00c03fff; 848 break; 849 850 case llvm::ELF::R_HEX_GOT_HI16: 851 bitMask = 0x00c03fff; 852 shift = 16; 853 alignment = 4; 854 break; 855 856 case llvm::ELF::R_HEX_GOT_32: 857 bitMask = 0xffffffff; 858 break; 859 860 case llvm::ELF::R_HEX_GOT_16: 861 bitMask = FINDBITMASK(pReloc.target()); 862 effectiveBits = 16; 863 break; 864 865 case llvm::ELF::R_HEX_GOT_32_6_X: 866 bitMask = 0xfff3fff; 867 shift = 6; 868 break; 869 870 case llvm::ELF::R_HEX_GOT_16_X: 871 bitMask = FINDBITMASK(pReloc.target()); 872 effectiveBits = 6; 873 break; 874 875 case llvm::ELF::R_HEX_GOT_11_X: 876 bitMask = FINDBITMASK(pReloc.target()); 877 result_u = GOT_S - GOT; 878 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result_u); 879 return HexagonRelocator::OK; 880 881 default: 882 // show proper error 883 fatal(diag::unsupported_relocation) << (int) 884 pReloc.type() << "mclinker@googlegroups.com"; 885 } 886 887 if ((shift != 0) && (result % alignment != 0)) 888 return HexagonRelocator::BadReloc; 889 890 result >>= shift; 891 892 if (effectiveBits) { 893 int32_t range = 1 << (effectiveBits - 1); 894 if ((result > range - 1) || (result < -range)) 895 return HexagonRelocator::Overflow; 896 } 897 pReloc.target() |= ApplyMask<int32_t>(bitMask, result); 898 return HexagonRelocator::OK; 899} 900 901// R_HEX_GOTREL_LO16: and its class of relocs 902// (S + A - GOT) : Signed Truncate 903HexagonRelocator::Result relocGOTREL(Relocation &pReloc, 904 HexagonRelocator &pParent) { 905 HexagonRelocator::Address S = pReloc.symValue(); 906 HexagonRelocator::DWord A = pReloc.addend(); 907 HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr(); 908 909 uint32_t bitMask = 0; 910 uint32_t alignment = 1; 911 uint32_t shift = 0; 912 913 uint32_t result = (uint32_t)(S + A - GOT); 914 915 switch (pReloc.type()) { 916 case llvm::ELF::R_HEX_GOTREL_LO16: 917 bitMask = 0x00c03fff; 918 break; 919 920 case llvm::ELF::R_HEX_GOTREL_HI16: 921 bitMask = 0x00c03fff; 922 shift = 16; 923 alignment = 4; 924 break; 925 926 case llvm::ELF::R_HEX_GOTREL_32: 927 bitMask = 0xffffffff; 928 break; 929 930 case llvm::ELF::R_HEX_GOTREL_32_6_X: 931 bitMask = 0x0fff3fff; 932 shift = 6; 933 break; 934 935 case llvm::ELF::R_HEX_GOTREL_16_X: 936 case llvm::ELF::R_HEX_GOTREL_11_X: 937 bitMask = FINDBITMASK(pReloc.target()); 938 break; 939 940 default: 941 // show proper error 942 fatal(diag::unsupported_relocation) << (int) 943 pReloc.type() << "mclinker@googlegroups.com"; 944 } 945 946 if (result % alignment != 0) 947 return HexagonRelocator::BadReloc; 948 949 result >>= shift; 950 951 pReloc.target() |= ApplyMask<uint32_t>(bitMask, result); 952 return HexagonRelocator::OK; 953} 954 955HexagonRelocator::Result unsupport(Relocation &pReloc, 956 HexagonRelocator &pParent) { 957 return HexagonRelocator::Unsupport; 958} 959