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