1//===- AArch64Relocator.cpp ----------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include <mcld/LinkerConfig.h> 11#include <mcld/IRBuilder.h> 12#include <mcld/Support/MsgHandling.h> 13#include <mcld/LD/LDSymbol.h> 14#include <mcld/LD/ELFFileFormat.h> 15#include <mcld/Object/ObjectBuilder.h> 16 17#include <llvm/ADT/Twine.h> 18#include <llvm/Support/DataTypes.h> 19#include <llvm/Support/ELF.h> 20#include <llvm/Support/Host.h> 21 22#include "AArch64Relocator.h" 23#include "AArch64RelocationFunctions.h" 24#include "AArch64RelocationHelpers.h" 25 26using namespace mcld; 27 28//===----------------------------------------------------------------------===// 29// Relocation Functions and Tables 30//===----------------------------------------------------------------------===// 31DECL_AARCH64_APPLY_RELOC_FUNCS 32 33/// the prototype of applying function 34typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc, 35 AArch64Relocator& pParent); 36 37// the table entry of applying functions 38class ApplyFunctionEntry { 39public: 40 ApplyFunctionEntry() {} 41 ApplyFunctionEntry(ApplyFunctionType pFunc, 42 const char* pName, 43 size_t pSize = 0) 44 : func(pFunc), name(pName), size(pSize) { } 45 ApplyFunctionType func; 46 const char* name; 47 size_t size; 48}; 49typedef std::map<Relocator::Type, ApplyFunctionEntry> ApplyFunctionMap; 50 51static const ApplyFunctionMap::value_type ApplyFunctionList[] = { 52 DECL_AARCH64_APPLY_RELOC_FUNC_PTRS(ApplyFunctionMap::value_type, 53 ApplyFunctionEntry) 54}; 55 56// declare the table of applying functions 57static ApplyFunctionMap ApplyFunctions(ApplyFunctionList, 58 ApplyFunctionList + sizeof(ApplyFunctionList)/sizeof(ApplyFunctionList[0])); 59 60//===----------------------------------------------------------------------===// 61// AArch64Relocator 62//===----------------------------------------------------------------------===// 63AArch64Relocator::AArch64Relocator(AArch64GNULDBackend& pParent, 64 const LinkerConfig& pConfig) 65 : Relocator(pConfig), 66 m_Target(pParent) { 67} 68 69AArch64Relocator::~AArch64Relocator() 70{ 71} 72 73Relocator::Result AArch64Relocator::applyRelocation(Relocation& pRelocation) 74{ 75 Relocation::Type type = pRelocation.type(); 76 // valid types are 0x0, 0x100-0x239 77 if ((type < 0x100 || type > 0x239) && (type != 0x0)) { 78 return Relocator::Unknown; 79 } 80 assert(ApplyFunctions.find(type) != ApplyFunctions.end()); 81 return ApplyFunctions[type].func(pRelocation, *this); 82} 83 84const char* AArch64Relocator::getName(Relocator::Type pType) const 85{ 86 assert(ApplyFunctions.find(pType) != ApplyFunctions.end()); 87 return ApplyFunctions[pType].name; 88} 89 90Relocator::Size AArch64Relocator::getSize(Relocation::Type pType) const 91{ 92 return ApplyFunctions[pType].size; 93} 94 95void AArch64Relocator::addCopyReloc(ResolveInfo& pSym) 96{ 97 Relocation& rel_entry = *getTarget().getRelaDyn().create(); 98 rel_entry.setType(R_AARCH64_COPY); 99 assert(pSym.outSymbol()->hasFragRef()); 100 rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 101 rel_entry.setSymInfo(&pSym); 102} 103 104/// defineSymbolForCopyReloc 105/// For a symbol needing copy relocation, define a copy symbol in the BSS 106/// section and all other reference to this symbol should refer to this 107/// copy. 108/// This is executed at scan relocation stage. 109LDSymbol& AArch64Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder, 110 const ResolveInfo& pSym) 111{ 112 // get or create corresponding BSS LDSection 113 LDSection* bss_sect_hdr = NULL; 114 ELFFileFormat* file_format = getTarget().getOutputFormat(); 115 if (ResolveInfo::ThreadLocal == pSym.type()) 116 bss_sect_hdr = &file_format->getTBSS(); 117 else 118 bss_sect_hdr = &file_format->getBSS(); 119 120 // get or create corresponding BSS SectionData 121 SectionData* bss_data = NULL; 122 if (bss_sect_hdr->hasSectionData()) 123 bss_data = bss_sect_hdr->getSectionData(); 124 else 125 bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr); 126 127 // Determine the alignment by the symbol value 128 // FIXME: here we use the largest alignment 129 uint32_t addralign = config().targets().bitclass() / 8; 130 131 // allocate space in BSS for the copy symbol 132 Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 133 uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_data, addralign); 134 bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 135 136 // change symbol binding to Global if it's a weak symbol 137 ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 138 if (binding == ResolveInfo::Weak) 139 binding = ResolveInfo::Global; 140 141 // Define the copy symbol in the bss section and resolve it 142 LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 143 pSym.name(), 144 (ResolveInfo::Type)pSym.type(), 145 ResolveInfo::Define, 146 binding, 147 pSym.size(), // size 148 0x0, // value 149 FragmentRef::Create(*frag, 0x0), 150 (ResolveInfo::Visibility)pSym.other()); 151 152 return *cpy_sym; 153} 154 155void 156AArch64Relocator::scanLocalReloc(Relocation& pReloc, const LDSection& pSection) 157{ 158 // rsym - The relocation target symbol 159 ResolveInfo* rsym = pReloc.symInfo(); 160 switch(pReloc.type()) { 161 case llvm::ELF::R_AARCH64_ABS64: 162 // If buiding PIC object (shared library or PIC executable), 163 // a dynamic relocations with RELATIVE type to this location is needed. 164 // Reserve an entry in .rel.dyn 165 if (config().isCodeIndep()) { 166 // set Rel bit 167 rsym->setReserved(rsym->reserved() | ReserveRel); 168 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 169 // set up the dyn rel directly 170 Relocation& reloc = helper_DynRela_init(rsym, 171 *pReloc.targetRef().frag(), 172 pReloc.targetRef().offset(), 173 R_AARCH64_RELATIVE, 174 *this); 175 getRelRelMap().record(pReloc, reloc); 176 } 177 return; 178 179 case llvm::ELF::R_AARCH64_ABS32: 180 case llvm::ELF::R_AARCH64_ABS16: 181 // If buiding PIC object (shared library or PIC executable), 182 // a dynamic relocations with RELATIVE type to this location is needed. 183 // Reserve an entry in .rel.dyn 184 if (config().isCodeIndep()) { 185 // set up the dyn rel directly 186 Relocation& reloc = helper_DynRela_init(rsym, 187 *pReloc.targetRef().frag(), 188 pReloc.targetRef().offset(), pReloc.type(), *this); 189 getRelRelMap().record(pReloc, reloc); 190 // set Rel bit 191 rsym->setReserved(rsym->reserved() | ReserveRel); 192 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 193 } 194 return; 195 196 case llvm::ELF::R_AARCH64_ADR_GOT_PAGE: 197 case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: { 198 // Symbol needs GOT entry, reserve entry in .got 199 // return if we already create GOT for this symbol 200 if (rsym->reserved() & ReserveGOT) 201 return; 202 // If building PIC object, a dynamic relocation with 203 // type RELATIVE is needed to relocate this GOT entry. 204 if (config().isCodeIndep()) 205 helper_GOT_init(pReloc, true, *this); 206 else 207 helper_GOT_init(pReloc, false, *this); 208 // set GOT bit 209 rsym->setReserved(rsym->reserved() | ReserveGOT); 210 return; 211 } 212 213 default: 214 break; 215 } 216} 217 218void AArch64Relocator::scanGlobalReloc(Relocation& pReloc, 219 IRBuilder& pBuilder, 220 const LDSection& pSection) 221{ 222 // rsym - The relocation target symbol 223 ResolveInfo* rsym = pReloc.symInfo(); 224 switch(pReloc.type()) { 225 case llvm::ELF::R_AARCH64_ABS64: 226 case llvm::ELF::R_AARCH64_ABS32: 227 case llvm::ELF::R_AARCH64_ABS16: 228 // Absolute relocation type, symbol may needs PLT entry or 229 // dynamic relocation entry 230 if (getTarget().symbolNeedsPLT(*rsym)) { 231 // create plt for this symbol if it does not have one 232 if (!(rsym->reserved() & ReservePLT)){ 233 // Symbol needs PLT entry, we need a PLT entry 234 // and the corresponding GOT and dynamic relocation entry 235 // in .got and .rel.plt. 236 helper_PLT_init(pReloc, *this); 237 // set PLT bit 238 rsym->setReserved(rsym->reserved() | ReservePLT); 239 } 240 } 241 242 if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 243 true)) { 244 // symbol needs dynamic relocation entry, set up the dynrel entry 245 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 246 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 247 addCopyReloc(*cpy_sym.resolveInfo()); 248 } 249 else { 250 // set Rel bit and the dyn rel 251 rsym->setReserved(rsym->reserved() | ReserveRel); 252 getTarget().checkAndSetHasTextRel(*pSection.getLink()); 253 if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() && 254 helper_use_relative_reloc(*rsym, *this)) { 255 Relocation& reloc = helper_DynRela_init(rsym, 256 *pReloc.targetRef().frag(), 257 pReloc.targetRef().offset(), 258 R_AARCH64_RELATIVE, 259 *this); 260 getRelRelMap().record(pReloc, reloc); 261 } 262 else { 263 Relocation& reloc = helper_DynRela_init(rsym, 264 *pReloc.targetRef().frag(), 265 pReloc.targetRef().offset(), 266 pReloc.type(), 267 *this); 268 getRelRelMap().record(pReloc, reloc); 269 } 270 } 271 } 272 return; 273 274 case llvm::ELF::R_AARCH64_PREL64: 275 case llvm::ELF::R_AARCH64_PREL32: 276 case llvm::ELF::R_AARCH64_PREL16: 277 if (getTarget().symbolNeedsPLT(*rsym) && 278 LinkerConfig::DynObj != config().codeGenType()) { 279 // create plt for this symbol if it does not have one 280 if (!(rsym->reserved() & ReservePLT)){ 281 // Symbol needs PLT entry, we need a PLT entry 282 // and the corresponding GOT and dynamic relocation entry 283 // in .got and .rel.plt. 284 helper_PLT_init(pReloc, *this); 285 // set PLT bit 286 rsym->setReserved(rsym->reserved() | ReservePLT); 287 } 288 } 289 290 // Only PC relative relocation against dynamic symbol needs a 291 // dynamic relocation. Only dynamic copy relocation is allowed 292 // and PC relative relocation will be resolved to the local copy. 293 // All other dynamic relocations may lead to run-time relocation 294 // overflow. 295 if (getTarget().isDynamicSymbol(*rsym) && 296 getTarget().symbolNeedsDynRel(*rsym, 297 (rsym->reserved() & ReservePLT), 298 false) && 299 getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 300 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 301 addCopyReloc(*cpy_sym.resolveInfo()); 302 } 303 return; 304 305 case llvm::ELF::R_AARCH64_CONDBR19: 306 case llvm::ELF::R_AARCH64_JUMP26: 307 case llvm::ELF::R_AARCH64_CALL26: { 308 // return if we already create plt for this symbol 309 if (rsym->reserved() & ReservePLT) 310 return; 311 312 // if the symbol's value can be decided at link time, then no need plt 313 if (getTarget().symbolFinalValueIsKnown(*rsym)) 314 return; 315 316 // if symbol is defined in the ouput file and it's not 317 // preemptible, no need plt 318 if (rsym->isDefine() && !rsym->isDyn() && 319 !getTarget().isSymbolPreemptible(*rsym)) { 320 return; 321 } 322 323 // Symbol needs PLT entry, we need to reserve a PLT entry 324 // and the corresponding GOT and dynamic relocation entry 325 // in .got and .rel.plt. 326 helper_PLT_init(pReloc, *this); 327 // set PLT bit 328 rsym->setReserved(rsym->reserved() | ReservePLT); 329 return; 330 } 331 332 case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21: 333 case R_AARCH64_ADR_PREL_PG_HI21_NC: 334 if (getTarget().symbolNeedsDynRel(*rsym, 335 (rsym->reserved() & ReservePLT), 336 false)) { 337 if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) { 338 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 339 addCopyReloc(*cpy_sym.resolveInfo()); 340 } 341 } 342 if (getTarget().symbolNeedsPLT(*rsym)) { 343 // create plt for this symbol if it does not have one 344 if (!(rsym->reserved() & ReservePLT)){ 345 // Symbol needs PLT entry, we need a PLT entry 346 // and the corresponding GOT and dynamic relocation entry 347 // in .got and .rel.plt. 348 helper_PLT_init(pReloc, *this); 349 // set PLT bit 350 rsym->setReserved(rsym->reserved() | ReservePLT); 351 } 352 } 353 return; 354 355 case llvm::ELF::R_AARCH64_ADR_GOT_PAGE: 356 case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: { 357 // Symbol needs GOT entry, reserve entry in .got 358 // return if we already create GOT for this symbol 359 if (rsym->reserved() & ReserveGOT) 360 return; 361 // if the symbol cannot be fully resolved at link time, then we need a 362 // dynamic relocation 363 if (!getTarget().symbolFinalValueIsKnown(*rsym)) 364 helper_GOT_init(pReloc, true, *this); 365 else 366 helper_GOT_init(pReloc, false, *this); 367 // set GOT bit 368 rsym->setReserved(rsym->reserved() | ReserveGOT); 369 return; 370 } 371 372 default: 373 break; 374 } 375} 376 377void AArch64Relocator::scanRelocation(Relocation& pReloc, 378 IRBuilder& pBuilder, 379 Module& pModule, 380 LDSection& pSection, 381 Input& pInput) 382{ 383 ResolveInfo* rsym = pReloc.symInfo(); 384 assert(NULL != rsym && 385 "ResolveInfo of relocation not set while scanRelocation"); 386 387 assert(NULL != pSection.getLink()); 388 if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 389 return; 390 391 // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation 392 // entries should be created. 393 // FIXME: Below judgements concern nothing about TLS related relocation 394 395 // rsym is local 396 if (rsym->isLocal()) 397 scanLocalReloc(pReloc, pSection); 398 // rsym is external 399 else 400 scanGlobalReloc(pReloc, pBuilder, pSection); 401 402 // check if we shoule issue undefined reference for the relocation target 403 // symbol 404 if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 405 issueUndefRef(pReloc, pSection, pInput); 406} 407 408//===----------------------------------------------------------------------===// 409// Each relocation function implementation 410//===----------------------------------------------------------------------===// 411 412// R_AARCH64_NONE 413Relocator::Result none(Relocation& pReloc, AArch64Relocator& pParent) 414{ 415 return Relocator::OK; 416} 417 418Relocator::Result unsupport(Relocation& pReloc, AArch64Relocator& pParent) 419{ 420 return Relocator::Unsupport; 421} 422 423// R_AARCH64_ABS64: S + A 424// R_AARCH64_ABS32: S + A 425// R_AARCH64_ABS16: S + A 426Relocator::Result abs(Relocation& pReloc, AArch64Relocator& pParent) 427{ 428 ResolveInfo* rsym = pReloc.symInfo(); 429 Relocator::DWord A = pReloc.target() + pReloc.addend(); 430 Relocator::DWord S = pReloc.symValue(); 431 Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc); 432 bool has_dyn_rel = (NULL != dyn_rel); 433 434 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 435 // If the flag of target section is not ALLOC, we will not scan this 436 // relocation but perform static relocation. (e.g., applying .debug section) 437 if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 438 pReloc.target() = S + A; 439 return Relocator::OK; 440 } 441 // A local symbol may need RELATIVE Type dynamic relocation 442 if (rsym->isLocal() && has_dyn_rel) { 443 dyn_rel->setAddend(S + A); 444 } 445 446 // An external symbol may need PLT and dynamic relocation 447 if (!rsym->isLocal()) { 448 if (rsym->reserved() & AArch64Relocator::ReservePLT) { 449 S = helper_get_PLT_address(*rsym, pParent); 450 } 451 // If we generate a dynamic relocation (except R_AARCH64_64_RELATIVE) 452 // for a place, we should not perform static relocation on it 453 // in order to keep the addend store in the place correct. 454 if (has_dyn_rel) { 455 if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() && 456 R_AARCH64_RELATIVE == dyn_rel->type()) { 457 dyn_rel->setAddend(S + A); 458 } 459 else { 460 dyn_rel->setAddend(A); 461 return Relocator::OK; 462 } 463 } 464 } 465 466 // perform static relocation 467 pReloc.target() = S + A; 468 return Relocator::OK; 469} 470 471// R_AARCH64_PREL64: S + A - P 472// R_AARCH64_PREL32: S + A - P 473// R_AARCH64_PREL16: S + A - P 474Relocator::Result rel(Relocation& pReloc, AArch64Relocator& pParent) 475{ 476 ResolveInfo* rsym = pReloc.symInfo(); 477 Relocator::Address S = pReloc.symValue(); 478 Relocator::DWord A = pReloc.addend(); 479 Relocator::DWord P = pReloc.place(); 480 481 if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type()) 482 A += pReloc.target() & get_mask(pParent.getSize(pReloc.type())); 483 else 484 A += pReloc.target(); 485 486 LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection(); 487 // If the flag of target section is not ALLOC, we will not scan this 488 // relocation but perform static relocation. (e.g., applying .debug section) 489 if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) { 490 // if plt entry exists, the S value is the plt entry address 491 if (!rsym->isLocal()) { 492 if (rsym->reserved() & AArch64Relocator::ReservePLT) { 493 S = helper_get_PLT_address(*rsym, pParent); 494 } 495 } 496 } 497 498 Relocator::DWord X = S + A - P; 499 pReloc.target() = X; 500 501 if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type() && 502 helper_check_signed_overflow(X, pParent.getSize(pReloc.type()))) 503 return Relocator::Overflow; 504 return Relocator::OK; 505} 506 507// R_AARCH64_ADD_ABS_LO12_NC: S + A 508Relocator::Result add_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent) 509{ 510 Relocator::Address value = 0x0; 511 Relocator::Address S = pReloc.symValue(); 512 Relocator::DWord A = pReloc.addend(); 513 514 value = helper_get_page_offset(S + A); 515 pReloc.target() = helper_reencode_add_imm(pReloc.target(), value); 516 517 return Relocator::OK; 518} 519 520// R_AARCH64_ADR_PREL_PG_HI21: ((PG(S + A) - PG(P)) >> 12) 521// R_AARCH64_ADR_PREL_PG_HI21_NC: ((PG(S + A) - PG(P)) >> 12) 522Relocator::Result 523adr_prel_pg_hi21(Relocation& pReloc, AArch64Relocator& pParent) 524{ 525 ResolveInfo* rsym = pReloc.symInfo(); 526 Relocator::Address S = pReloc.symValue(); 527 // if plt entry exists, the S value is the plt entry address 528 if (rsym->reserved() & AArch64Relocator::ReservePLT) { 529 S = helper_get_PLT_address(*rsym, pParent); 530 } 531 Relocator::DWord A = pReloc.addend(); 532 Relocator::DWord P = pReloc.place() ; 533 Relocator::DWord X = helper_get_page_address(S + A) - 534 helper_get_page_address(P); 535 536 pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12)); 537 538 return Relocator::OK; 539} 540 541// R_AARCH64_CALL26: S + A - P 542// R_AARCH64_JUMP26: S + A - P 543Relocator::Result call(Relocation& pReloc, AArch64Relocator& pParent) 544{ 545 // If target is undefined weak symbol, we only need to jump to the 546 // next instruction unless it has PLT entry. Rewrite instruction 547 // to NOP. 548 if (pReloc.symInfo()->isWeak() && 549 pReloc.symInfo()->isUndef() && 550 !pReloc.symInfo()->isDyn() && 551 !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) { 552 // change target to NOP 553 pReloc.target() = 0xd503201f; 554 return Relocator::OK; 555 } 556 557 Relocator::Address S = pReloc.symValue(); 558 Relocator::DWord A = pReloc.addend(); 559 Relocator::Address P = pReloc.place(); 560 561 // S depends on PLT exists or not 562 if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT) 563 S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 564 565 Relocator::DWord X = S + A - P; 566 // TODO: check overflow.. 567 568 pReloc.target() = helper_reencode_branch_offset_26(pReloc.target(), X >> 2); 569 570 return Relocator::OK; 571} 572 573// R_AARCH64_CONDBR19: S + A - P 574Relocator::Result condbr(Relocation& pReloc, AArch64Relocator& pParent) 575{ 576 // If target is undefined weak symbol, we only need to jump to the 577 // next instruction unless it has PLT entry. Rewrite instruction 578 // to NOP. 579 if (pReloc.symInfo()->isWeak() && 580 pReloc.symInfo()->isUndef() && 581 !pReloc.symInfo()->isDyn() && 582 !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) { 583 // change target to NOP 584 pReloc.target() = 0xd503201f; 585 return Relocator::OK; 586 } 587 588 Relocator::Address S = pReloc.symValue(); 589 Relocator::DWord A = pReloc.addend(); 590 Relocator::Address P = pReloc.place(); 591 592 // S depends on PLT exists or not 593 if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT) 594 S = helper_get_PLT_address(*pReloc.symInfo(), pParent); 595 596 Relocator::DWord X = S + A - P; 597 // TODO: check overflow.. 598 599 pReloc.target() = helper_reencode_cond_branch_ofs_19(pReloc.target(), X >> 2); 600 601 return Relocator::OK; 602} 603 604// R_AARCH64_ADR_GOT_PAGE: Page(G(GDAT(S+A))) - Page(P) 605Relocator::Result adr_got_page(Relocation& pReloc, AArch64Relocator& pParent) 606{ 607 if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) { 608 return Relocator::BadReloc; 609 } 610 611 Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent); 612 Relocator::DWord A = pReloc.addend(); 613 Relocator::Address P = pReloc.place(); 614 Relocator::DWord X = helper_get_page_address(GOT_S + A) - 615 helper_get_page_address(P); 616 617 pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12)); 618 619 // setup got entry value if needed 620 AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 621 if (NULL != got_entry && AArch64Relocator::SymVal == got_entry->getValue()) 622 got_entry->setValue(pReloc.symValue()); 623 // setup relocation addend if needed 624 Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc); 625 if ((NULL != dyn_rela) && (AArch64Relocator::SymVal == dyn_rela->addend())) { 626 dyn_rela->setAddend(pReloc.symValue()); 627 } 628 return Relocator::OK; 629} 630 631// R_AARCH64_LD64_GOT_LO12_NC: G(GDAT(S+A)) 632Relocator::Result ld64_got_lo12(Relocation& pReloc, AArch64Relocator& pParent) 633{ 634 if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) { 635 return Relocator::BadReloc; 636 } 637 638 Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent); 639 Relocator::DWord A = pReloc.addend(); 640 Relocator::DWord X = helper_get_page_offset(GOT_S + A); 641 642 pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 3)); 643 644 // setup got entry value if needed 645 AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo()); 646 if (NULL != got_entry && AArch64Relocator::SymVal == got_entry->getValue()) 647 got_entry->setValue(pReloc.symValue()); 648 649 // setup relocation addend if needed 650 Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc); 651 if ((NULL != dyn_rela) && (AArch64Relocator::SymVal == dyn_rela->addend())) { 652 dyn_rela->setAddend(pReloc.symValue()); 653 } 654 655 return Relocator::OK; 656} 657 658// R_AARCH64_LDST8_ABS_LO12_NC: S + A 659// R_AARCH64_LDST16_ABS_LO12_NC: S + A 660// R_AARCH64_LDST32_ABS_LO12_NC: S + A 661// R_AARCH64_LDST64_ABS_LO12_NC: S + A 662// R_AARCH64_LDST128_ABS_LO12_NC: S + A 663Relocator::Result ldst_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent) 664{ 665 Relocator::Address S = pReloc.symValue(); 666 Relocator::DWord A = pReloc.addend(); 667 Relocator::DWord X = helper_get_page_offset(S + A); 668 669 switch(pReloc.type()) { 670 case llvm::ELF::R_AARCH64_LDST8_ABS_LO12_NC: 671 pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), X); 672 break; 673 case llvm::ELF::R_AARCH64_LDST16_ABS_LO12_NC: 674 pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), 675 (X >> 1)); 676 break; 677 case llvm::ELF::R_AARCH64_LDST32_ABS_LO12_NC: 678 pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), 679 (X >> 2)); 680 break; 681 case llvm::ELF::R_AARCH64_LDST64_ABS_LO12_NC: 682 pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), 683 (X >> 3)); 684 break; 685 case llvm::ELF::R_AARCH64_LDST128_ABS_LO12_NC: 686 pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), 687 (X >> 4)); 688 break; 689 default: 690 break; 691 } 692 return Relocator::OK; 693} 694 695