1 //===- ARMLDBackend.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 "ARM.h" 10 #include "ARMGNUInfo.h" 11 #include "ARMELFDynamic.h" 12 #include "ARMLDBackend.h" 13 #include "ARMRelocator.h" 14 #include "ARMToARMStub.h" 15 #include "ARMToTHMStub.h" 16 #include "THMToTHMStub.h" 17 #include "THMToARMStub.h" 18 19 #include <cstring> 20 21 #include <llvm/ADT/Triple.h> 22 #include <llvm/ADT/Twine.h> 23 #include <llvm/Support/ELF.h> 24 #include <llvm/Support/Casting.h> 25 26 #include <mcld/IRBuilder.h> 27 #include <mcld/LinkerConfig.h> 28 #include <mcld/Fragment/FillFragment.h> 29 #include <mcld/Fragment/AlignFragment.h> 30 #include <mcld/Fragment/RegionFragment.h> 31 #include <mcld/Support/MemoryRegion.h> 32 #include <mcld/Support/MemoryArea.h> 33 #include <mcld/Support/MsgHandling.h> 34 #include <mcld/Support/TargetRegistry.h> 35 #include <mcld/Fragment/Stub.h> 36 #include <mcld/LD/BranchIslandFactory.h> 37 #include <mcld/LD/StubFactory.h> 38 #include <mcld/Object/ObjectBuilder.h> 39 #include <mcld/Fragment/NullFragment.h> 40 #include <mcld/LD/LDContext.h> 41 #include <mcld/Target/GNUInfo.h> 42 43 using namespace mcld; 44 45 //===----------------------------------------------------------------------===// 46 // ARMGNULDBackend 47 //===----------------------------------------------------------------------===// 48 ARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo) 49 : GNULDBackend(pConfig, pInfo), 50 m_pRelocator(NULL), 51 m_pGOT(NULL), 52 m_pPLT(NULL), 53 m_pRelDyn(NULL), 54 m_pRelPLT(NULL), 55 m_pDynamic(NULL), 56 m_pGOTSymbol(NULL), 57 m_pEXIDXStart(NULL), 58 m_pEXIDXEnd(NULL), 59 m_pEXIDX(NULL), 60 m_pEXTAB(NULL), 61 m_pAttributes(NULL) { 62 } 63 64 ARMGNULDBackend::~ARMGNULDBackend() 65 { 66 delete m_pRelocator; 67 delete m_pGOT; 68 delete m_pPLT; 69 delete m_pRelDyn; 70 delete m_pRelPLT; 71 delete m_pDynamic; 72 } 73 74 void ARMGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder) 75 { 76 // FIXME: Currently we set exidx and extab to "Exception" and directly emit 77 // them from input 78 m_pEXIDX = pBuilder.CreateSection(".ARM.exidx", 79 LDFileFormat::Target, 80 llvm::ELF::SHT_ARM_EXIDX, 81 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER, 82 config().targets().bitclass() / 8); 83 m_pEXTAB = pBuilder.CreateSection(".ARM.extab", 84 LDFileFormat::Target, 85 llvm::ELF::SHT_PROGBITS, 86 llvm::ELF::SHF_ALLOC, 87 0x1); 88 m_pAttributes = pBuilder.CreateSection(".ARM.attributes", 89 LDFileFormat::Target, 90 llvm::ELF::SHT_ARM_ATTRIBUTES, 91 0x0, 92 0x1); 93 94 if (LinkerConfig::Object != config().codeGenType()) { 95 ELFFileFormat* file_format = getOutputFormat(); 96 97 // initialize .got 98 LDSection& got = file_format->getGOT(); 99 m_pGOT = new ARMGOT(got); 100 101 // initialize .plt 102 LDSection& plt = file_format->getPLT(); 103 m_pPLT = new ARMPLT(plt, *m_pGOT); 104 105 // initialize .rel.plt 106 LDSection& relplt = file_format->getRelPlt(); 107 relplt.setLink(&plt); 108 // create SectionData and ARMRelDynSection 109 m_pRelPLT = new OutputRelocSection(pModule, relplt); 110 111 // initialize .rel.dyn 112 LDSection& reldyn = file_format->getRelDyn(); 113 m_pRelDyn = new OutputRelocSection(pModule, reldyn); 114 } 115 } 116 117 void ARMGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) 118 { 119 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the 120 // same name in input 121 if (LinkerConfig::Object != config().codeGenType()) { 122 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 123 "_GLOBAL_OFFSET_TABLE_", 124 ResolveInfo::Object, 125 ResolveInfo::Define, 126 ResolveInfo::Local, 127 0x0, // size 128 0x0, // value 129 FragmentRef::Null(), 130 ResolveInfo::Hidden); 131 } 132 if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) { 133 FragmentRef* exidx_start = 134 FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0); 135 FragmentRef* exidx_end = 136 FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 137 m_pEXIDX->size()); 138 m_pEXIDXStart = 139 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 140 "__exidx_start", 141 ResolveInfo::Object, 142 ResolveInfo::Define, 143 ResolveInfo::Local, 144 0x0, // size 145 0x0, // value 146 exidx_start, // FragRef 147 ResolveInfo::Default); 148 149 m_pEXIDXEnd = 150 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 151 "__exidx_end", 152 ResolveInfo::Object, 153 ResolveInfo::Define, 154 ResolveInfo::Local, 155 0x0, // size 156 0x0, // value 157 exidx_end, // FragRef 158 ResolveInfo::Default); 159 // change __exidx_start/_end to local dynamic category 160 if (NULL != m_pEXIDXStart) 161 pModule.getSymbolTable().changeToDynamic(*m_pEXIDXStart); 162 if (NULL != m_pEXIDXEnd) 163 pModule.getSymbolTable().changeToDynamic(*m_pEXIDXEnd); 164 } else { 165 m_pEXIDXStart = 166 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 167 "__exidx_start", 168 ResolveInfo::NoType, 169 ResolveInfo::Define, 170 ResolveInfo::Absolute, 171 0x0, // size 172 0x0, // value 173 FragmentRef::Null(), 174 ResolveInfo::Default); 175 176 m_pEXIDXEnd = 177 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 178 "__exidx_end", 179 ResolveInfo::NoType, 180 ResolveInfo::Define, 181 ResolveInfo::Absolute, 182 0x0, // size 183 0x0, // value 184 FragmentRef::Null(), 185 ResolveInfo::Default); 186 } 187 } 188 189 bool ARMGNULDBackend::initRelocator() 190 { 191 if (NULL == m_pRelocator) { 192 m_pRelocator = new ARMRelocator(*this, config()); 193 } 194 return true; 195 } 196 197 Relocator* ARMGNULDBackend::getRelocator() 198 { 199 assert(NULL != m_pRelocator); 200 return m_pRelocator; 201 } 202 203 void ARMGNULDBackend::doPreLayout(IRBuilder& pBuilder) 204 { 205 // initialize .dynamic data 206 if (!config().isCodeStatic() && NULL == m_pDynamic) 207 m_pDynamic = new ARMELFDynamic(*this, config()); 208 209 // set .got size 210 // when building shared object, the .got section is must 211 if (LinkerConfig::Object != config().codeGenType()) { 212 if (LinkerConfig::DynObj == config().codeGenType() || 213 m_pGOT->hasGOT1() || 214 NULL != m_pGOTSymbol) { 215 m_pGOT->finalizeSectionSize(); 216 defineGOTSymbol(pBuilder); 217 } 218 219 // set .plt size 220 if (m_pPLT->hasPLT1()) 221 m_pPLT->finalizeSectionSize(); 222 223 ELFFileFormat* file_format = getOutputFormat(); 224 // set .rel.dyn size 225 if (!m_pRelDyn->empty()) { 226 assert(!config().isCodeStatic() && 227 "static linkage should not result in a dynamic relocation section"); 228 file_format->getRelDyn().setSize( 229 m_pRelDyn->numOfRelocs() * getRelEntrySize()); 230 } 231 232 // set .rel.plt size 233 if (!m_pRelPLT->empty()) { 234 assert(!config().isCodeStatic() && 235 "static linkage should not result in a dynamic relocation section"); 236 file_format->getRelPlt().setSize( 237 m_pRelPLT->numOfRelocs() * getRelEntrySize()); 238 } 239 } 240 } 241 242 void ARMGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) 243 { 244 const ELFFileFormat *file_format = getOutputFormat(); 245 246 // apply PLT 247 if (file_format->hasPLT()) { 248 // Since we already have the size of LDSection PLT, m_pPLT should not be 249 // NULL. 250 assert(NULL != m_pPLT); 251 m_pPLT->applyPLT0(); 252 m_pPLT->applyPLT1(); 253 } 254 255 // apply GOT 256 if (file_format->hasGOT()) { 257 // Since we already have the size of GOT, m_pGOT should not be NULL. 258 assert(NULL != m_pGOT); 259 if (LinkerConfig::DynObj == config().codeGenType()) 260 m_pGOT->applyGOT0(file_format->getDynamic().addr()); 261 else { 262 // executable file and object file? should fill with zero. 263 m_pGOT->applyGOT0(0); 264 } 265 } 266 } 267 268 /// dynamic - the dynamic section of the target machine. 269 /// Use co-variant return type to return its own dynamic section. 270 ARMELFDynamic& ARMGNULDBackend::dynamic() 271 { 272 assert(NULL != m_pDynamic); 273 return *m_pDynamic; 274 } 275 276 /// dynamic - the dynamic section of the target machine. 277 /// Use co-variant return type to return its own dynamic section. 278 const ARMELFDynamic& ARMGNULDBackend::dynamic() const 279 { 280 assert(NULL != m_pDynamic); 281 return *m_pDynamic; 282 } 283 284 void ARMGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) 285 { 286 // define symbol _GLOBAL_OFFSET_TABLE_ when .got create 287 if (m_pGOTSymbol != NULL) { 288 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 289 "_GLOBAL_OFFSET_TABLE_", 290 ResolveInfo::Object, 291 ResolveInfo::Define, 292 ResolveInfo::Local, 293 0x0, // size 294 0x0, // value 295 FragmentRef::Create(*(m_pGOT->begin()), 0x0), 296 ResolveInfo::Hidden); 297 } 298 else { 299 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 300 "_GLOBAL_OFFSET_TABLE_", 301 ResolveInfo::Object, 302 ResolveInfo::Define, 303 ResolveInfo::Local, 304 0x0, // size 305 0x0, // value 306 FragmentRef::Create(*(m_pGOT->begin()), 0x0), 307 ResolveInfo::Hidden); 308 } 309 310 } 311 312 uint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection, 313 MemoryRegion& pRegion) const 314 { 315 assert(pRegion.size() && "Size of MemoryRegion is zero!"); 316 317 const ELFFileFormat* file_format = getOutputFormat(); 318 319 if (&pSection == m_pAttributes || 320 &pSection == m_pEXIDX || 321 &pSection == m_pEXTAB) { 322 // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab 323 // directly from the input file. 324 const SectionData* sect_data = pSection.getSectionData(); 325 SectionData::const_iterator frag_iter, frag_end = sect_data->end(); 326 uint8_t* out_offset = pRegion.start(); 327 for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) { 328 size_t size = frag_iter->size(); 329 switch(frag_iter->getKind()) { 330 case Fragment::Fillment: { 331 const FillFragment& fill_frag = 332 llvm::cast<FillFragment>(*frag_iter); 333 if (0 == fill_frag.getValueSize()) { 334 // virtual fillment, ignore it. 335 break; 336 } 337 338 memset(out_offset, fill_frag.getValue(), fill_frag.size()); 339 break; 340 } 341 case Fragment::Region: { 342 const RegionFragment& region_frag = 343 llvm::cast<RegionFragment>(*frag_iter); 344 const uint8_t* start = region_frag.getRegion().start(); 345 memcpy(out_offset, start, size); 346 break; 347 } 348 case Fragment::Alignment: { 349 const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter); 350 uint64_t count = size / align_frag.getValueSize(); 351 switch (align_frag.getValueSize()) { 352 case 1u: 353 std::memset(out_offset, align_frag.getValue(), count); 354 break; 355 default: 356 llvm::report_fatal_error( 357 "unsupported value size for align fragment emission yet.\n"); 358 break; 359 } // end switch 360 break; 361 } 362 case Fragment::Null: { 363 assert(0x0 == size); 364 break; 365 } 366 default: 367 llvm::report_fatal_error("unsupported fragment type.\n"); 368 break; 369 } // end switch 370 out_offset += size; 371 } // end for 372 return pRegion.size(); 373 } // end if 374 375 if (&pSection == &(file_format->getPLT())) { 376 assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!"); 377 uint64_t result = m_pPLT->emit(pRegion); 378 return result; 379 } 380 381 if (&pSection == &(file_format->getGOT())) { 382 assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!"); 383 uint64_t result = m_pGOT->emit(pRegion); 384 return result; 385 } 386 fatal(diag::unrecognized_output_sectoin) 387 << pSection.name() 388 << "mclinker (at) googlegroups.com"; 389 return 0x0; 390 } 391 392 /// finalizeSymbol - finalize the symbol value 393 bool ARMGNULDBackend::finalizeTargetSymbols() 394 { 395 return true; 396 } 397 398 bool ARMGNULDBackend::mergeSection(Module& pModule, LDSection& pSection) 399 { 400 switch (pSection.type()) { 401 case llvm::ELF::SHT_ARM_ATTRIBUTES: { 402 // FIXME: (Luba) 403 // Handle ARM attributes in the right way. 404 // In current milestone, we goes through the shortcut. 405 // It reads input's ARM attributes and copies the first ARM attributes 406 // into the output file. The correct way is merge these sections, not 407 // just copy. 408 if (0 != m_pAttributes->size()) 409 return true; 410 411 // First time we meet a ARM attributes section. 412 SectionData* sd = IRBuilder::CreateSectionData(*m_pAttributes); 413 ObjectBuilder::MoveSectionData(*pSection.getSectionData(), *sd); 414 return true; 415 } 416 default: { 417 ObjectBuilder builder(config(), pModule); 418 return builder.MergeSection(pSection); 419 } 420 } // end of switch 421 return true; 422 } 423 424 bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD) 425 { 426 Fragment* frag = NULL; 427 uint32_t offset = pInput.fileOffset() + pSD.getSection().offset(); 428 uint32_t size = pSD.getSection().size(); 429 430 MemoryRegion* region = pInput.memArea()->request(offset, size); 431 if (NULL == region) { 432 // If the input section's size is zero, we got a NULL region. 433 // use a virtual fill fragment 434 frag = new FillFragment(0x0, 0, 0); 435 } 436 else { 437 frag = new RegionFragment(*region); 438 } 439 440 ObjectBuilder::AppendFragment(*frag, pSD); 441 return true; 442 } 443 444 ARMGOT& ARMGNULDBackend::getGOT() 445 { 446 assert(NULL != m_pGOT && "GOT section not exist"); 447 return *m_pGOT; 448 } 449 450 const ARMGOT& ARMGNULDBackend::getGOT() const 451 { 452 assert(NULL != m_pGOT && "GOT section not exist"); 453 return *m_pGOT; 454 } 455 456 ARMPLT& ARMGNULDBackend::getPLT() 457 { 458 assert(NULL != m_pPLT && "PLT section not exist"); 459 return *m_pPLT; 460 } 461 462 const ARMPLT& ARMGNULDBackend::getPLT() const 463 { 464 assert(NULL != m_pPLT && "PLT section not exist"); 465 return *m_pPLT; 466 } 467 468 OutputRelocSection& ARMGNULDBackend::getRelDyn() 469 { 470 assert(NULL != m_pRelDyn && ".rel.dyn section not exist"); 471 return *m_pRelDyn; 472 } 473 474 const OutputRelocSection& ARMGNULDBackend::getRelDyn() const 475 { 476 assert(NULL != m_pRelDyn && ".rel.dyn section not exist"); 477 return *m_pRelDyn; 478 } 479 480 OutputRelocSection& ARMGNULDBackend::getRelPLT() 481 { 482 assert(NULL != m_pRelPLT && ".rel.plt section not exist"); 483 return *m_pRelPLT; 484 } 485 486 const OutputRelocSection& ARMGNULDBackend::getRelPLT() const 487 { 488 assert(NULL != m_pRelPLT && ".rel.plt section not exist"); 489 return *m_pRelPLT; 490 } 491 492 unsigned int 493 ARMGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const 494 { 495 const ELFFileFormat* file_format = getOutputFormat(); 496 497 if (&pSectHdr == &file_format->getGOT()) { 498 if (config().options().hasNow()) 499 return SHO_RELRO_LAST; 500 return SHO_DATA; 501 } 502 503 if (&pSectHdr == &file_format->getPLT()) 504 return SHO_PLT; 505 506 if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) { 507 // put ARM.exidx and ARM.extab in the same order of .eh_frame 508 return SHO_EXCEPTION; 509 } 510 511 return SHO_UNDEFINED; 512 } 513 514 /// doRelax 515 bool 516 ARMGNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished) 517 { 518 assert(NULL != getStubFactory() && NULL != getBRIslandFactory()); 519 520 bool isRelaxed = false; 521 ELFFileFormat* file_format = getOutputFormat(); 522 // check branch relocs and create the related stubs if needed 523 Module::obj_iterator input, inEnd = pModule.obj_end(); 524 for (input = pModule.obj_begin(); input != inEnd; ++input) { 525 LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); 526 for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { 527 if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) 528 continue; 529 RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end(); 530 for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) { 531 Relocation* relocation = llvm::cast<Relocation>(reloc); 532 533 switch (relocation->type()) { 534 case llvm::ELF::R_ARM_PC24: 535 case llvm::ELF::R_ARM_CALL: 536 case llvm::ELF::R_ARM_JUMP24: 537 case llvm::ELF::R_ARM_PLT32: 538 case llvm::ELF::R_ARM_THM_CALL: 539 case llvm::ELF::R_ARM_THM_XPC22: 540 case llvm::ELF::R_ARM_THM_JUMP24: 541 case llvm::ELF::R_ARM_THM_JUMP19: 542 case llvm::ELF::R_ARM_V4BX: { 543 // calculate the possible symbol value 544 uint64_t sym_value = 0x0; 545 LDSymbol* symbol = relocation->symInfo()->outSymbol(); 546 if (symbol->hasFragRef()) { 547 uint64_t value = symbol->fragRef()->getOutputOffset(); 548 uint64_t addr = 549 symbol->fragRef()->frag()->getParent()->getSection().addr(); 550 sym_value = addr + value; 551 } 552 if (relocation->symInfo()->isGlobal() && 553 (relocation->symInfo()->reserved() & ARMRelocator::ReservePLT) != 0x0) { 554 // FIXME: we need to find out the address of the specific plt entry 555 assert(file_format->hasPLT()); 556 sym_value = file_format->getPLT().addr(); 557 } 558 559 Stub* stub = getStubFactory()->create(*relocation, // relocation 560 sym_value, // symbol value 561 pBuilder, 562 *getBRIslandFactory()); 563 if (NULL != stub) { 564 // a stub symbol should be local 565 assert(NULL != stub->symInfo() && stub->symInfo()->isLocal()); 566 LDSection& symtab = file_format->getSymTab(); 567 LDSection& strtab = file_format->getStrTab(); 568 569 // increase the size of .symtab and .strtab if needed 570 if (config().targets().is32Bits()) 571 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym)); 572 else 573 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym)); 574 symtab.setInfo(symtab.getInfo() + 1); 575 strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1); 576 577 isRelaxed = true; 578 } 579 break; 580 } 581 default: 582 break; 583 } // end of switch 584 585 } // for all relocations 586 } // for all relocation section 587 } // for all inputs 588 589 // find the first fragment w/ invalid offset due to stub insertion 590 Fragment* invalid = NULL; 591 pFinished = true; 592 for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(), 593 island_end = getBRIslandFactory()->end(); island != island_end; ++island) { 594 if ((*island).end() == file_format->getText().getSectionData()->end()) 595 break; 596 597 Fragment* exit = (*island).end(); 598 if (((*island).offset() + (*island).size()) > exit->getOffset()) { 599 invalid = exit; 600 pFinished = false; 601 break; 602 } 603 } 604 605 // reset the offset of invalid fragments 606 while (NULL != invalid) { 607 invalid->setOffset(invalid->getPrevNode()->getOffset() + 608 invalid->getPrevNode()->size()); 609 invalid = invalid->getNextNode(); 610 } 611 612 // reset the size of .text 613 if (isRelaxed) { 614 file_format->getText().setSize( 615 file_format->getText().getSectionData()->back().getOffset() + 616 file_format->getText().getSectionData()->back().size()); 617 } 618 return isRelaxed; 619 } 620 621 /// initTargetStubs 622 bool ARMGNULDBackend::initTargetStubs() 623 { 624 if (NULL != getStubFactory()) { 625 getStubFactory()->addPrototype(new ARMToARMStub(config().isCodeIndep())); 626 getStubFactory()->addPrototype(new ARMToTHMStub(config().isCodeIndep())); 627 getStubFactory()->addPrototype(new THMToTHMStub(config().isCodeIndep())); 628 getStubFactory()->addPrototype(new THMToARMStub(config().isCodeIndep())); 629 return true; 630 } 631 return false; 632 } 633 634 /// doCreateProgramHdrs - backend can implement this function to create the 635 /// target-dependent segments 636 void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule) 637 { 638 if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) { 639 // make PT_ARM_EXIDX 640 ELFSegment* exidx_seg = elfSegmentTable().produce(llvm::ELF::PT_ARM_EXIDX, 641 llvm::ELF::PF_R); 642 exidx_seg->addSection(m_pEXIDX); 643 } 644 } 645 646 namespace mcld { 647 648 //===----------------------------------------------------------------------===// 649 /// createARMLDBackend - the help funtion to create corresponding ARMLDBackend 650 /// 651 TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget, 652 const LinkerConfig& pConfig) 653 { 654 if (pConfig.targets().triple().isOSDarwin()) { 655 assert(0 && "MachO linker is not supported yet"); 656 /** 657 return new ARMMachOLDBackend(createARMMachOArchiveReader, 658 createARMMachOObjectReader, 659 createARMMachOObjectWriter); 660 **/ 661 } 662 if (pConfig.targets().triple().isOSWindows()) { 663 assert(0 && "COFF linker is not supported yet"); 664 /** 665 return new ARMCOFFLDBackend(createARMCOFFArchiveReader, 666 createARMCOFFObjectReader, 667 createARMCOFFObjectWriter); 668 **/ 669 } 670 return new ARMGNULDBackend(pConfig, new ARMGNUInfo(pConfig.targets().triple())); 671 } 672 673 } // namespace of mcld 674 675 //===----------------------------------------------------------------------===// 676 // Force static initialization. 677 //===----------------------------------------------------------------------===// 678 extern "C" void MCLDInitializeARMLDBackend() { 679 // Register the linker backend 680 mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend); 681 mcld::TargetRegistry::RegisterTargetLDBackend(TheThumbTarget, createARMLDBackend); 682 } 683 684