1 //===- AArch64LDBackend.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 "AArch64.h" 10 #include "AArch64CA53Erratum835769Stub.h" 11 #include "AArch64CA53Erratum843419Stub.h" 12 #include "AArch64CA53Erratum843419Stub2.h" 13 #include "AArch64ELFDynamic.h" 14 #include "AArch64GNUInfo.h" 15 #include "AArch64InsnHelpers.h" 16 #include "AArch64LDBackend.h" 17 #include "AArch64LongBranchStub.h" 18 #include "AArch64Relocator.h" 19 20 #include "mcld/IRBuilder.h" 21 #include "mcld/LinkerConfig.h" 22 #include "mcld/Fragment/AlignFragment.h" 23 #include "mcld/Fragment/FillFragment.h" 24 #include "mcld/Fragment/NullFragment.h" 25 #include "mcld/Fragment/RegionFragment.h" 26 #include "mcld/Fragment/Stub.h" 27 #include "mcld/LD/BranchIslandFactory.h" 28 #include "mcld/LD/ELFFileFormat.h" 29 #include "mcld/LD/ELFSegment.h" 30 #include "mcld/LD/ELFSegmentFactory.h" 31 #include "mcld/LD/LDContext.h" 32 #include "mcld/LD/StubFactory.h" 33 #include "mcld/Support/MemoryRegion.h" 34 #include "mcld/Support/MemoryArea.h" 35 #include "mcld/Support/MsgHandling.h" 36 #include "mcld/Support/TargetRegistry.h" 37 #include "mcld/Target/ELFAttribute.h" 38 #include "mcld/Target/GNUInfo.h" 39 #include "mcld/Object/ObjectBuilder.h" 40 41 #include <llvm/ADT/Triple.h> 42 #include <llvm/ADT/Twine.h> 43 #include <llvm/Support/Casting.h> 44 #include <llvm/Support/ELF.h> 45 46 #include <cstring> 47 48 namespace mcld { 49 50 //===----------------------------------------------------------------------===// 51 // AArch64GNULDBackend 52 //===----------------------------------------------------------------------===// 53 AArch64GNULDBackend::AArch64GNULDBackend(const LinkerConfig& pConfig, 54 GNUInfo* pInfo) 55 : GNULDBackend(pConfig, pInfo), 56 m_pRelocator(NULL), 57 m_pGOT(NULL), 58 m_pGOTPLT(NULL), 59 m_pPLT(NULL), 60 m_pRelaDyn(NULL), 61 m_pRelaPLT(NULL), 62 m_pDynamic(NULL), 63 m_pGOTSymbol(NULL) { 64 } 65 66 AArch64GNULDBackend::~AArch64GNULDBackend() { 67 if (m_pRelocator != NULL) 68 delete m_pRelocator; 69 if (m_pGOT == m_pGOTPLT) { 70 if (m_pGOT != NULL) 71 delete m_pGOT; 72 } else { 73 if (m_pGOT != NULL) 74 delete m_pGOT; 75 if (m_pGOTPLT != NULL) 76 delete m_pGOTPLT; 77 } 78 if (m_pPLT != NULL) 79 delete m_pPLT; 80 if (m_pRelaDyn != NULL) 81 delete m_pRelaDyn; 82 if (m_pRelaPLT != NULL) 83 delete m_pRelaPLT; 84 if (m_pDynamic != NULL) 85 delete m_pDynamic; 86 } 87 88 void AArch64GNULDBackend::initTargetSections(Module& pModule, 89 ObjectBuilder& pBuilder) { 90 if (LinkerConfig::Object != config().codeGenType()) { 91 ELFFileFormat* file_format = getOutputFormat(); 92 93 // initialize .got 94 LDSection& got = file_format->getGOT(); 95 m_pGOT = new AArch64GOT(got); 96 if (config().options().hasNow()) { 97 // when -z now is given, there will be only one .got section (contains 98 // both GOTPLT and normal GOT entries), create GOT0 for .got section and 99 // set m_pGOTPLT to the same .got 100 m_pGOT->createGOT0(); 101 m_pGOTPLT = m_pGOT; 102 } else { 103 // Otherwise, got should be seperated to two sections, .got and .got.plt 104 // initialize .got.plt 105 LDSection& gotplt = file_format->getGOTPLT(); 106 m_pGOTPLT = new AArch64GOT(gotplt); 107 m_pGOTPLT->createGOT0(); 108 } 109 110 // initialize .plt 111 LDSection& plt = file_format->getPLT(); 112 m_pPLT = new AArch64PLT(plt, *m_pGOTPLT); 113 114 // initialize .rela.plt 115 LDSection& relaplt = file_format->getRelaPlt(); 116 relaplt.setLink(&plt); 117 m_pRelaPLT = new OutputRelocSection(pModule, relaplt); 118 119 // initialize .rela.dyn 120 LDSection& reladyn = file_format->getRelaDyn(); 121 m_pRelaDyn = new OutputRelocSection(pModule, reladyn); 122 } 123 } 124 125 void AArch64GNULDBackend::initTargetSymbols(IRBuilder& pBuilder, 126 Module& pModule) { 127 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the 128 // same name in input 129 if (LinkerConfig::Object != config().codeGenType()) { 130 m_pGOTSymbol = 131 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 132 "_GLOBAL_OFFSET_TABLE_", 133 ResolveInfo::Object, 134 ResolveInfo::Define, 135 ResolveInfo::Local, 136 0x0, // size 137 0x0, // value 138 FragmentRef::Null(), 139 ResolveInfo::Hidden); 140 } 141 } 142 143 bool AArch64GNULDBackend::initRelocator() { 144 if (m_pRelocator == NULL) { 145 m_pRelocator = new AArch64Relocator(*this, config()); 146 } 147 return true; 148 } 149 150 const Relocator* AArch64GNULDBackend::getRelocator() const { 151 assert(m_pRelocator != NULL); 152 return m_pRelocator; 153 } 154 155 Relocator* AArch64GNULDBackend::getRelocator() { 156 assert(m_pRelocator != NULL); 157 return m_pRelocator; 158 } 159 160 void AArch64GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) { 161 // define symbol _GLOBAL_OFFSET_TABLE_ when .got create 162 if (m_pGOTSymbol != NULL) { 163 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 164 "_GLOBAL_OFFSET_TABLE_", 165 ResolveInfo::Object, 166 ResolveInfo::Define, 167 ResolveInfo::Local, 168 0x0, // size 169 0x0, // value 170 FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0), 171 ResolveInfo::Hidden); 172 } else { 173 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 174 "_GLOBAL_OFFSET_TABLE_", 175 ResolveInfo::Object, 176 ResolveInfo::Define, 177 ResolveInfo::Local, 178 0x0, // size 179 0x0, // value 180 FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0), 181 ResolveInfo::Hidden); 182 } 183 } 184 185 void AArch64GNULDBackend::doPreLayout(IRBuilder& pBuilder) { 186 // initialize .dynamic data 187 if (!config().isCodeStatic() && m_pDynamic == NULL) 188 m_pDynamic = new AArch64ELFDynamic(*this, config()); 189 190 if (LinkerConfig::Object != config().codeGenType()) { 191 // set .got size 192 if (config().options().hasNow()) { 193 // when building shared object, the GOTPLT section is must 194 if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() || 195 m_pGOTSymbol != NULL) { 196 m_pGOT->finalizeSectionSize(); 197 defineGOTSymbol(pBuilder); 198 } 199 } else { 200 // when building shared object, the GOTPLT section is must 201 if (LinkerConfig::DynObj == config().codeGenType() || 202 m_pGOTPLT->hasGOT1() || m_pGOTSymbol != NULL) { 203 m_pGOTPLT->finalizeSectionSize(); 204 defineGOTSymbol(pBuilder); 205 } 206 if (m_pGOT->hasGOT1()) 207 m_pGOT->finalizeSectionSize(); 208 } 209 210 // set .plt size 211 if (m_pPLT->hasPLT1()) 212 m_pPLT->finalizeSectionSize(); 213 214 ELFFileFormat* file_format = getOutputFormat(); 215 // set .rela.dyn size 216 if (!m_pRelaDyn->empty()) { 217 assert( 218 !config().isCodeStatic() && 219 "static linkage should not result in a dynamic relocation section"); 220 file_format->getRelaDyn().setSize(m_pRelaDyn->numOfRelocs() * 221 getRelaEntrySize()); 222 } 223 224 // set .rela.plt size 225 if (!m_pRelaPLT->empty()) { 226 assert( 227 !config().isCodeStatic() && 228 "static linkage should not result in a dynamic relocation section"); 229 file_format->getRelaPlt().setSize(m_pRelaPLT->numOfRelocs() * 230 getRelaEntrySize()); 231 } 232 } 233 } 234 235 void AArch64GNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) { 236 const ELFFileFormat* file_format = getOutputFormat(); 237 238 // apply PLT 239 if (file_format->hasPLT()) { 240 assert(m_pPLT != NULL); 241 m_pPLT->applyPLT0(); 242 m_pPLT->applyPLT1(); 243 } 244 245 // apply GOTPLT 246 if ((config().options().hasNow() && file_format->hasGOT()) || 247 file_format->hasGOTPLT()) { 248 assert(m_pGOTPLT != NULL); 249 if (LinkerConfig::DynObj == config().codeGenType()) 250 m_pGOTPLT->applyGOT0(file_format->getDynamic().addr()); 251 else { 252 // executable file and object file? should fill with zero. 253 m_pGOTPLT->applyGOT0(0); 254 } 255 } 256 } 257 258 AArch64ELFDynamic& AArch64GNULDBackend::dynamic() { 259 assert(m_pDynamic != NULL); 260 return *m_pDynamic; 261 } 262 263 const AArch64ELFDynamic& AArch64GNULDBackend::dynamic() const { 264 assert(m_pDynamic != NULL); 265 return *m_pDynamic; 266 } 267 268 uint64_t AArch64GNULDBackend::emitSectionData(const LDSection& pSection, 269 MemoryRegion& pRegion) const { 270 assert(pRegion.size() && "Size of MemoryRegion is zero!"); 271 272 const ELFFileFormat* file_format = getOutputFormat(); 273 274 if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) { 275 uint64_t result = m_pPLT->emit(pRegion); 276 return result; 277 } 278 279 if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) { 280 uint64_t result = m_pGOT->emit(pRegion); 281 return result; 282 } 283 284 if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) { 285 uint64_t result = m_pGOT->emit(pRegion); 286 return result; 287 } 288 289 return pRegion.size(); 290 } 291 292 unsigned int AArch64GNULDBackend::getTargetSectionOrder( 293 const LDSection& pSectHdr) const { 294 const ELFFileFormat* file_format = getOutputFormat(); 295 296 if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) { 297 if (config().options().hasNow()) 298 return SHO_RELRO; 299 return SHO_RELRO_LAST; 300 } 301 302 if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT())) 303 return SHO_NON_RELRO_FIRST; 304 305 if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT())) 306 return SHO_PLT; 307 308 return SHO_UNDEFINED; 309 } 310 311 void AArch64GNULDBackend::scanErrata(Module& pModule, 312 IRBuilder& pBuilder, 313 size_t& num_new_stubs, 314 size_t& stubs_strlen) { 315 // TODO: Implement AArch64 ErrataStubFactory to create the specific erratum 316 // stub and simplify the logics. 317 for (Module::iterator sect = pModule.begin(), sectEnd = pModule.end(); 318 sect != sectEnd; ++sect) { 319 if (((*sect)->kind() == LDFileFormat::TEXT) && (*sect)->hasSectionData()) { 320 SectionData* sd = (*sect)->getSectionData(); 321 for (SectionData::iterator it = sd->begin(), ie = sd->end(); it != ie; 322 ++it) { 323 Fragment* frag = llvm::dyn_cast<RegionFragment>(it); 324 if (frag != NULL) { 325 FragmentRef* frag_ref = FragmentRef::Create(*frag, 0); 326 for (unsigned offset = 0; offset < frag->size(); 327 offset += AArch64InsnHelpers::InsnSize) { 328 Stub* stub = getStubFactory()->create(*frag_ref, 329 pBuilder, 330 *getBRIslandFactory()); 331 if (stub != NULL) { 332 // A stub symbol should be local 333 assert(stub->symInfo() != NULL && stub->symInfo()->isLocal()); 334 const AArch64CA53ErratumStub* erratum_stub = 335 reinterpret_cast<const AArch64CA53ErratumStub*>(stub); 336 assert(erratum_stub != NULL); 337 // Rewrite the erratum instruction as a branch to the stub. 338 uint64_t offset = frag_ref->offset() + 339 erratum_stub->getErratumInsnOffset(); 340 Relocation* reloc = 341 Relocation::Create(llvm::ELF::R_AARCH64_JUMP26, 342 *(FragmentRef::Create(*frag, offset)), 343 /* pAddend */0); 344 reloc->setSymInfo(stub->symInfo()); 345 reloc->target() = AArch64InsnHelpers::buildBranchInsn(); 346 addExtraRelocation(reloc); 347 348 ++num_new_stubs; 349 stubs_strlen += stub->symInfo()->nameSize() + 1; 350 } 351 352 frag_ref->assign(*frag, offset + AArch64InsnHelpers::InsnSize); 353 } // for each INSN 354 } 355 } // for each FRAGMENT 356 } 357 } // for each TEXT section 358 } 359 360 bool AArch64GNULDBackend::doRelax(Module& pModule, 361 IRBuilder& pBuilder, 362 bool& pFinished) { 363 assert(getStubFactory() != NULL && getBRIslandFactory() != NULL); 364 365 // Number of new stubs added 366 size_t num_new_stubs = 0; 367 // String lengh to hold new stub symbols 368 size_t stubs_strlen = 0; 369 370 if (config().targets().fixCA53Erratum835769() || 371 config().targets().fixCA53Erratum843419()) { 372 scanErrata(pModule, pBuilder, num_new_stubs, stubs_strlen); 373 } 374 375 ELFFileFormat* file_format = getOutputFormat(); 376 // check branch relocs and create the related stubs if needed 377 Module::obj_iterator input, inEnd = pModule.obj_end(); 378 for (input = pModule.obj_begin(); input != inEnd; ++input) { 379 LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); 380 for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { 381 if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) 382 continue; 383 RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end(); 384 for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) { 385 Relocation* relocation = llvm::cast<Relocation>(reloc); 386 387 switch (relocation->type()) { 388 case llvm::ELF::R_AARCH64_CALL26: 389 case llvm::ELF::R_AARCH64_JUMP26: { 390 // calculate the possible symbol value 391 uint64_t sym_value = 0x0; 392 LDSymbol* symbol = relocation->symInfo()->outSymbol(); 393 if (symbol->hasFragRef()) { 394 uint64_t value = symbol->fragRef()->getOutputOffset(); 395 uint64_t addr = 396 symbol->fragRef()->frag()->getParent()->getSection().addr(); 397 sym_value = addr + value; 398 } 399 if ((relocation->symInfo()->reserved() & 400 AArch64Relocator::ReservePLT) != 0x0) { 401 // FIXME: we need to find out the address of the specific plt 402 // entry 403 assert(file_format->hasPLT()); 404 sym_value = file_format->getPLT().addr(); 405 } 406 Stub* stub = getStubFactory()->create(*relocation, // relocation 407 sym_value, // symbol value 408 pBuilder, 409 *getBRIslandFactory()); 410 if (stub != NULL) { 411 // a stub symbol should be local 412 assert(stub->symInfo() != NULL && stub->symInfo()->isLocal()); 413 // reset the branch target of the reloc to this stub instead 414 relocation->setSymInfo(stub->symInfo()); 415 416 ++num_new_stubs; 417 stubs_strlen += stub->symInfo()->nameSize() + 1; 418 } 419 break; 420 } 421 default: { 422 break; 423 } 424 } // end of switch 425 } // for all relocations 426 } // for all relocation section 427 } // for all inputs 428 429 // Find the first fragment w/ invalid offset due to stub insertion. 430 std::vector<Fragment*> invalid_frags; 431 pFinished = true; 432 for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(), 433 island_end = getBRIslandFactory()->end(); 434 island != island_end; 435 ++island) { 436 if ((*island).size() > stubGroupSize()) { 437 error(diag::err_no_space_to_place_stubs) << stubGroupSize(); 438 return false; 439 } 440 441 if ((*island).numOfStubs() == 0) { 442 continue; 443 } 444 445 Fragment* exit = &*(*island).end(); 446 if (exit == &*(*island).begin()->getParent()->end()) { 447 continue; 448 } 449 450 if (((*island).offset() + (*island).size()) > exit->getOffset()) { 451 if (invalid_frags.empty() || 452 (invalid_frags.back()->getParent() != (*island).getParent())) { 453 invalid_frags.push_back(exit); 454 pFinished = false; 455 } 456 continue; 457 } 458 } 459 460 // Reset the offset of invalid fragments. 461 for (auto it = invalid_frags.begin(), ie = invalid_frags.end(); it != ie; 462 ++it) { 463 Fragment* invalid = *it; 464 while (invalid != NULL) { 465 invalid->setOffset(invalid->getPrevNode()->getOffset() + 466 invalid->getPrevNode()->size()); 467 invalid = invalid->getNextNode(); 468 } 469 } 470 471 // Fix up the size of .symtab, .strtab, and TEXT sections 472 if (num_new_stubs == 0) { 473 return false; 474 } else { 475 switch (config().options().getStripSymbolMode()) { 476 case GeneralOptions::StripSymbolMode::StripAllSymbols: 477 case GeneralOptions::StripSymbolMode::StripLocals: 478 break; 479 default: { 480 LDSection& symtab = file_format->getSymTab(); 481 LDSection& strtab = file_format->getStrTab(); 482 483 symtab.setSize(symtab.size() + 484 sizeof(llvm::ELF::Elf64_Sym) * num_new_stubs); 485 symtab.setInfo(symtab.getInfo() + num_new_stubs); 486 strtab.setSize(strtab.size() + stubs_strlen); 487 } 488 } // switch (config().options().getStripSymbolMode()) 489 490 SectionData* prev = NULL; 491 for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(), 492 island_end = getBRIslandFactory()->end(); 493 island != island_end; 494 ++island) { 495 SectionData* sd = (*island).begin()->getParent(); 496 if ((*island).numOfStubs() != 0) { 497 if (sd != prev) { 498 sd->getSection().setSize(sd->back().getOffset() + sd->back().size()); 499 } 500 } 501 prev = sd; 502 } 503 return true; 504 } // if (num_new_stubs == 0) 505 } 506 507 bool AArch64GNULDBackend::initTargetStubs() { 508 StubFactory* factory = getStubFactory(); 509 if (factory != NULL) { 510 factory->addPrototype(new AArch64LongBranchStub(config().isCodeIndep())); 511 if (config().targets().fixCA53Erratum835769()) { 512 factory->addPrototype(new AArch64CA53Erratum835769Stub()); 513 } 514 if (config().targets().fixCA53Erratum843419()) { 515 factory->addPrototype(new AArch64CA53Erratum843419Stub()); 516 factory->addPrototype(new AArch64CA53Erratum843419Stub2()); 517 } 518 return true; 519 } 520 return false; 521 } 522 523 void AArch64GNULDBackend::doCreateProgramHdrs(Module& pModule) { 524 } 525 526 bool AArch64GNULDBackend::finalizeTargetSymbols() { 527 return true; 528 } 529 530 bool AArch64GNULDBackend::mergeSection(Module& pModule, 531 const Input& pInput, 532 LDSection& pSection) { 533 return true; 534 } 535 536 bool AArch64GNULDBackend::readSection(Input& pInput, SectionData& pSD) { 537 return true; 538 } 539 540 AArch64GOT& AArch64GNULDBackend::getGOT() { 541 assert(m_pGOT != NULL && "GOT section not exist"); 542 return *m_pGOT; 543 } 544 545 const AArch64GOT& AArch64GNULDBackend::getGOT() const { 546 assert(m_pGOT != NULL && "GOT section not exist"); 547 return *m_pGOT; 548 } 549 550 AArch64GOT& AArch64GNULDBackend::getGOTPLT() { 551 assert(m_pGOTPLT != NULL && "GOTPLT section not exist"); 552 return *m_pGOTPLT; 553 } 554 555 const AArch64GOT& AArch64GNULDBackend::getGOTPLT() const { 556 assert(m_pGOTPLT != NULL && "GOTPLT section not exist"); 557 return *m_pGOTPLT; 558 } 559 560 AArch64PLT& AArch64GNULDBackend::getPLT() { 561 assert(m_pPLT != NULL && "PLT section not exist"); 562 return *m_pPLT; 563 } 564 565 const AArch64PLT& AArch64GNULDBackend::getPLT() const { 566 assert(m_pPLT != NULL && "PLT section not exist"); 567 return *m_pPLT; 568 } 569 570 OutputRelocSection& AArch64GNULDBackend::getRelaDyn() { 571 assert(m_pRelaDyn != NULL && ".rela.dyn section not exist"); 572 return *m_pRelaDyn; 573 } 574 575 const OutputRelocSection& AArch64GNULDBackend::getRelaDyn() const { 576 assert(m_pRelaDyn != NULL && ".rela.dyn section not exist"); 577 return *m_pRelaDyn; 578 } 579 580 OutputRelocSection& AArch64GNULDBackend::getRelaPLT() { 581 assert(m_pRelaPLT != NULL && ".rela.plt section not exist"); 582 return *m_pRelaPLT; 583 } 584 585 const OutputRelocSection& AArch64GNULDBackend::getRelaPLT() const { 586 assert(m_pRelaPLT != NULL && ".rela.plt section not exist"); 587 return *m_pRelaPLT; 588 } 589 590 //===----------------------------------------------------------------------===// 591 // createAArch64LDBackend - the help funtion to create corresponding 592 // AArch64LDBackend 593 //===----------------------------------------------------------------------===// 594 TargetLDBackend* createAArch64LDBackend(const LinkerConfig& pConfig) { 595 if (pConfig.targets().triple().isOSDarwin()) { 596 assert(0 && "MachO linker is not supported yet"); 597 /** 598 return new AArch64MachOLDBackend(createAArch64MachOArchiveReader, 599 createAArch64MachOObjectReader, 600 createAArch64MachOObjectWriter); 601 **/ 602 } 603 if (pConfig.targets().triple().isOSWindows()) { 604 assert(0 && "COFF linker is not supported yet"); 605 /** 606 return new AArch64COFFLDBackend(createAArch64COFFArchiveReader, 607 createAArch64COFFObjectReader, 608 createAArch64COFFObjectWriter); 609 **/ 610 } 611 return new AArch64GNULDBackend( 612 pConfig, new AArch64GNUInfo(pConfig.targets().triple())); 613 } 614 615 } // namespace mcld 616 617 //===----------------------------------------------------------------------===// 618 // Force static initialization. 619 //===----------------------------------------------------------------------===// 620 extern "C" void MCLDInitializeAArch64LDBackend() { 621 // Register the linker backend 622 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheAArch64Target, 623 mcld::createAArch64LDBackend); 624 } 625