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