ARMLDBackend.cpp revision 2bf3f881f79c4d883f379e63725e788c310739a3
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 398 399/// preMergeSections - hooks to be executed before merging sections 400void ARMGNULDBackend::preMergeSections(Module& pModule) { 401 scanInputExceptionSections(pModule); 402} 403 404/// postMergeSections - hooks to be executed after merging sections 405void ARMGNULDBackend::postMergeSections(Module& pModule) { 406 if (m_pEXIDX->hasSectionData()) { 407 // Append the NullFragment so that __exidx_end can be correctly inserted. 408 NullFragment* null = new NullFragment(m_pEXIDX->getSectionData()); 409 null->setOffset(m_pEXIDX->size()); 410 } 411} 412 413bool ARMGNULDBackend::mergeSection(Module& pModule, 414 const Input& pInput, 415 LDSection& pSection) { 416 switch (pSection.type()) { 417 case llvm::ELF::SHT_ARM_ATTRIBUTES: { 418 return attribute().merge(pInput, pSection); 419 } 420 421 case llvm::ELF::SHT_ARM_EXIDX: { 422 assert(pSection.getLink() != NULL); 423 if ((pSection.getLink()->kind() == LDFileFormat::Ignore) || 424 (pSection.getLink()->kind() == LDFileFormat::Folded)) { 425 // if the target section of the .ARM.exidx is Ignore, then it should be 426 // ignored as well 427 pSection.setKind(LDFileFormat::Ignore); 428 return true; 429 } 430 431 if (!m_pEXIDX->hasSectionData()) { 432 // Create SectionData for m_pEXIDX. 433 SectionData* sectData = IRBuilder::CreateSectionData(*m_pEXIDX); 434 435 // Initialize the alignment of m_pEXIDX. 436 const size_t alignExIdx = 4; 437 m_pEXIDX->setAlign(alignExIdx); 438 439 // Insert an AlignFragment to the beginning of m_pEXIDX. 440 AlignFragment* frag = 441 new AlignFragment(/*alignment*/alignExIdx, 442 /*the filled value*/0x0, 443 /*the size of filled value*/1u, 444 /*max bytes to emit*/alignExIdx - 1); 445 frag->setOffset(0); 446 frag->setParent(sectData); 447 sectData->getFragmentList().push_back(frag); 448 m_pEXIDX->setSize(frag->size()); 449 } 450 451 // Move RegionFragment from pSection to m_pEXIDX. 452 uint64_t offset = m_pEXIDX->size(); 453 SectionData::FragmentListType& src = 454 pSection.getSectionData()->getFragmentList(); 455 SectionData::FragmentListType& dst = 456 m_pEXIDX->getSectionData()->getFragmentList(); 457 SectionData::FragmentListType::iterator frag = src.begin(); 458 SectionData::FragmentListType::iterator fragEnd = src.end(); 459 while (frag != fragEnd) { 460 if (frag->getKind() != Fragment::Region) { 461 ++frag; 462 } else { 463 frag->setParent(m_pEXIDX->getSectionData()); 464 frag->setOffset(offset); 465 offset += frag->size(); 466 dst.splice(dst.end(), src, frag++); 467 } 468 } 469 470 // Update the size of m_pEXIDX. 471 m_pEXIDX->setSize(offset); 472 return true; 473 } 474 475 default: { 476 ObjectBuilder builder(pModule); 477 builder.MergeSection(pInput, pSection); 478 return true; 479 } 480 } // end of switch 481 return true; 482} 483 484void ARMGNULDBackend::setUpReachedSectionsForGC( 485 const Module& pModule, 486 GarbageCollection::SectionReachedListMap& pSectReachedListMap) const { 487 // traverse all the input relocations to find the relocation sections applying 488 // .ARM.exidx sections 489 Module::const_obj_iterator input, inEnd = pModule.obj_end(); 490 for (input = pModule.obj_begin(); input != inEnd; ++input) { 491 LDContext::const_sect_iterator rs, 492 rsEnd = (*input)->context()->relocSectEnd(); 493 for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { 494 // bypass the discarded relocation section 495 // 1. its section kind is changed to Ignore. (The target section is a 496 // discarded group section.) 497 // 2. it has no reloc data. (All symbols in the input relocs are in the 498 // discarded group sections) 499 LDSection* reloc_sect = *rs; 500 LDSection* apply_sect = reloc_sect->getLink(); 501 if ((LDFileFormat::Ignore == reloc_sect->kind()) || 502 (!reloc_sect->hasRelocData())) 503 continue; 504 505 if (llvm::ELF::SHT_ARM_EXIDX == apply_sect->type()) { 506 // 1. set up the reference according to relocations 507 bool add_first = false; 508 GarbageCollection::SectionListTy* reached_sects = NULL; 509 RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end(); 510 for (reloc_it = reloc_sect->getRelocData()->begin(); reloc_it != rEnd; 511 ++reloc_it) { 512 Relocation* reloc = llvm::cast<Relocation>(reloc_it); 513 ResolveInfo* sym = reloc->symInfo(); 514 // only the target symbols defined in the input fragments can make the 515 // reference 516 if (sym == NULL) 517 continue; 518 if (!sym->isDefine() || !sym->outSymbol()->hasFragRef()) 519 continue; 520 521 // only the target symbols defined in the concerned sections can make 522 // the reference 523 const LDSection* target_sect = 524 &sym->outSymbol()->fragRef()->frag()->getParent()->getSection(); 525 if (target_sect->kind() != LDFileFormat::TEXT && 526 target_sect->kind() != LDFileFormat::DATA && 527 target_sect->kind() != LDFileFormat::BSS) 528 continue; 529 530 // setup the reached list, if we first add the element to reached list 531 // of this section, create an entry in ReachedSections map 532 if (!add_first) { 533 reached_sects = &pSectReachedListMap.getReachedList(*apply_sect); 534 add_first = true; 535 } 536 reached_sects->insert(target_sect); 537 } 538 reached_sects = NULL; 539 add_first = false; 540 // 2. set up the reference from XXX to .ARM.exidx.XXX 541 assert(apply_sect->getLink() != NULL); 542 pSectReachedListMap.addReference(*apply_sect->getLink(), *apply_sect); 543 } 544 } 545 } 546} 547 548bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD) { 549 Fragment* frag = NULL; 550 uint32_t offset = pInput.fileOffset() + pSD.getSection().offset(); 551 uint32_t size = pSD.getSection().size(); 552 553 llvm::StringRef region = pInput.memArea()->request(offset, size); 554 if (region.size() == 0) { 555 // If the input section's size is zero, we got a NULL region. 556 // use a virtual fill fragment 557 frag = new FillFragment(0x0, 0, 0); 558 } else { 559 frag = new RegionFragment(region); 560 } 561 562 ObjectBuilder::AppendFragment(*frag, pSD); 563 return true; 564} 565 566ARMGOT& ARMGNULDBackend::getGOT() { 567 assert(m_pGOT != NULL && "GOT section not exist"); 568 return *m_pGOT; 569} 570 571const ARMGOT& ARMGNULDBackend::getGOT() const { 572 assert(m_pGOT != NULL && "GOT section not exist"); 573 return *m_pGOT; 574} 575 576ARMPLT& ARMGNULDBackend::getPLT() { 577 assert(m_pPLT != NULL && "PLT section not exist"); 578 return *m_pPLT; 579} 580 581const ARMPLT& ARMGNULDBackend::getPLT() const { 582 assert(m_pPLT != NULL && "PLT section not exist"); 583 return *m_pPLT; 584} 585 586OutputRelocSection& ARMGNULDBackend::getRelDyn() { 587 assert(m_pRelDyn != NULL && ".rel.dyn section not exist"); 588 return *m_pRelDyn; 589} 590 591const OutputRelocSection& ARMGNULDBackend::getRelDyn() const { 592 assert(m_pRelDyn != NULL && ".rel.dyn section not exist"); 593 return *m_pRelDyn; 594} 595 596OutputRelocSection& ARMGNULDBackend::getRelPLT() { 597 assert(m_pRelPLT != NULL && ".rel.plt section not exist"); 598 return *m_pRelPLT; 599} 600 601const OutputRelocSection& ARMGNULDBackend::getRelPLT() const { 602 assert(m_pRelPLT != NULL && ".rel.plt section not exist"); 603 return *m_pRelPLT; 604} 605 606ARMELFAttributeData& ARMGNULDBackend::getAttributeData() { 607 assert(m_pAttrData != NULL && ".ARM.attributes section not exist"); 608 return *m_pAttrData; 609} 610 611const ARMELFAttributeData& ARMGNULDBackend::getAttributeData() const { 612 assert(m_pAttrData != NULL && ".ARM.attributes section not exist"); 613 return *m_pAttrData; 614} 615 616unsigned int ARMGNULDBackend::getTargetSectionOrder( 617 const LDSection& pSectHdr) const { 618 const ELFFileFormat* file_format = getOutputFormat(); 619 620 if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) { 621 if (config().options().hasNow()) 622 return SHO_RELRO_LAST; 623 return SHO_DATA; 624 } 625 626 if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT())) 627 return SHO_PLT; 628 629 if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) { 630 // put ARM.exidx and ARM.extab in the same order of .eh_frame 631 return SHO_EXCEPTION; 632 } 633 634 return SHO_UNDEFINED; 635} 636 637/// relax - the relaxation pass 638bool ARMGNULDBackend::relax(Module& pModule, IRBuilder& pBuilder) { 639 if (!GNULDBackend::relax(pModule, pBuilder)) { 640 return false; 641 } 642 rewriteARMExIdxSection(pModule); 643 return true; 644} 645 646/// doRelax 647bool ARMGNULDBackend::doRelax(Module& pModule, 648 IRBuilder& pBuilder, 649 bool& pFinished) { 650 assert(getStubFactory() != NULL && getBRIslandFactory() != NULL); 651 652 bool isRelaxed = false; 653 ELFFileFormat* file_format = getOutputFormat(); 654 // check branch relocs and create the related stubs if needed 655 Module::obj_iterator input, inEnd = pModule.obj_end(); 656 for (input = pModule.obj_begin(); input != inEnd; ++input) { 657 LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); 658 for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { 659 if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) 660 continue; 661 RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end(); 662 for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) { 663 Relocation* relocation = llvm::cast<Relocation>(reloc); 664 665 switch (relocation->type()) { 666 case llvm::ELF::R_ARM_PC24: 667 case llvm::ELF::R_ARM_CALL: 668 case llvm::ELF::R_ARM_JUMP24: 669 case llvm::ELF::R_ARM_PLT32: 670 case llvm::ELF::R_ARM_THM_CALL: 671 case llvm::ELF::R_ARM_THM_XPC22: 672 case llvm::ELF::R_ARM_THM_JUMP24: 673 case llvm::ELF::R_ARM_THM_JUMP19: { 674 // calculate the possible symbol value 675 uint64_t sym_value = 0x0; 676 LDSymbol* symbol = relocation->symInfo()->outSymbol(); 677 if (symbol->hasFragRef()) { 678 uint64_t value = symbol->fragRef()->getOutputOffset(); 679 uint64_t addr = 680 symbol->fragRef()->frag()->getParent()->getSection().addr(); 681 sym_value = addr + value; 682 } 683 if ((relocation->symInfo()->reserved() & 684 ARMRelocator::ReservePLT) != 0x0) { 685 // FIXME: we need to find out the address of the specific plt 686 // entry 687 assert(file_format->hasPLT()); 688 sym_value = file_format->getPLT().addr(); 689 } 690 Stub* stub = getStubFactory()->create(*relocation, // relocation 691 sym_value, // symbol value 692 pBuilder, 693 *getBRIslandFactory()); 694 if (stub != NULL) { 695 switch (config().options().getStripSymbolMode()) { 696 case GeneralOptions::StripSymbolMode::StripAllSymbols: 697 case GeneralOptions::StripSymbolMode::StripLocals: 698 break; 699 default: { 700 // a stub symbol should be local 701 assert(stub->symInfo() != NULL && stub->symInfo()->isLocal()); 702 LDSection& symtab = file_format->getSymTab(); 703 LDSection& strtab = file_format->getStrTab(); 704 705 // increase the size of .symtab and .strtab if needed 706 if (config().targets().is32Bits()) 707 symtab.setSize(symtab.size() + 708 sizeof(llvm::ELF::Elf32_Sym)); 709 else 710 symtab.setSize(symtab.size() + 711 sizeof(llvm::ELF::Elf64_Sym)); 712 symtab.setInfo(symtab.getInfo() + 1); 713 strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 714 1); 715 } 716 } // end of switch 717 isRelaxed = true; 718 } 719 break; 720 } 721 case llvm::ELF::R_ARM_V4BX: 722 /* FIXME: bypass R_ARM_V4BX relocation now */ 723 break; 724 default: 725 break; 726 } // end of switch 727 } // for all relocations 728 } // for all relocation section 729 } // for all inputs 730 731 // find the first fragment w/ invalid offset due to stub insertion 732 Fragment* invalid = NULL; 733 pFinished = true; 734 for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(), 735 island_end = getBRIslandFactory()->end(); 736 island != island_end; 737 ++island) { 738 if ((*island).end() == file_format->getText().getSectionData()->end()) 739 break; 740 741 Fragment* exit = (*island).end(); 742 if (((*island).offset() + (*island).size()) > exit->getOffset()) { 743 invalid = exit; 744 pFinished = false; 745 break; 746 } 747 } 748 749 // reset the offset of invalid fragments 750 while (invalid != NULL) { 751 invalid->setOffset(invalid->getPrevNode()->getOffset() + 752 invalid->getPrevNode()->size()); 753 invalid = invalid->getNextNode(); 754 } 755 756 // reset the size of .text 757 if (isRelaxed) { 758 file_format->getText().setSize( 759 file_format->getText().getSectionData()->back().getOffset() + 760 file_format->getText().getSectionData()->back().size()); 761 } 762 return isRelaxed; 763} 764 765/// initTargetStubs 766bool ARMGNULDBackend::initTargetStubs() { 767 if (getStubFactory() != NULL) { 768 getStubFactory()->addPrototype(new ARMToARMStub(config().isCodeIndep())); 769 getStubFactory()->addPrototype(new ARMToTHMStub(config().isCodeIndep())); 770 getStubFactory()->addPrototype( 771 new THMToTHMStub(config().isCodeIndep(), m_pAttrData->usingThumb2())); 772 getStubFactory()->addPrototype( 773 new THMToARMStub(config().isCodeIndep(), m_pAttrData->usingThumb2())); 774 return true; 775 } 776 return false; 777} 778 779/// maxFwdBranchOffset 780int64_t ARMGNULDBackend::maxFwdBranchOffset() { 781 if (m_pAttrData->usingThumb2()) { 782 return THM2_MAX_FWD_BRANCH_OFFSET; 783 } else { 784 return THM_MAX_FWD_BRANCH_OFFSET; 785 } 786} 787 788/// maxBwdBranchOffset 789int64_t ARMGNULDBackend::maxBwdBranchOffset() { 790 if (m_pAttrData->usingThumb2()) { 791 return THM2_MAX_BWD_BRANCH_OFFSET; 792 } else { 793 return THM_MAX_BWD_BRANCH_OFFSET; 794 } 795} 796 797/// doCreateProgramHdrs - backend can implement this function to create the 798/// target-dependent segments 799void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule) { 800 if (m_pEXIDX != NULL && m_pEXIDX->size() != 0x0) { 801 // make PT_ARM_EXIDX 802 ELFSegment* exidx_seg = 803 elfSegmentTable().produce(llvm::ELF::PT_ARM_EXIDX, llvm::ELF::PF_R); 804 exidx_seg->append(m_pEXIDX); 805 } 806} 807 808/// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe 809/// function pointer access 810bool ARMGNULDBackend::mayHaveUnsafeFunctionPointerAccess( 811 const LDSection& pSection) const { 812 llvm::StringRef name(pSection.name()); 813 return !name.startswith(".ARM.exidx") && !name.startswith(".ARM.extab") && 814 GNULDBackend::mayHaveUnsafeFunctionPointerAccess(pSection); 815} 816 817//===----------------------------------------------------------------------===// 818/// createARMLDBackend - the help funtion to create corresponding ARMLDBackend 819/// 820TargetLDBackend* createARMLDBackend(const LinkerConfig& pConfig) { 821 if (pConfig.targets().triple().isOSDarwin()) { 822 assert(0 && "MachO linker is not supported yet"); 823 /** 824 return new ARMMachOLDBackend(createARMMachOArchiveReader, 825 createARMMachOObjectReader, 826 createARMMachOObjectWriter); 827 **/ 828 } 829 if (pConfig.targets().triple().isOSWindows()) { 830 assert(0 && "COFF linker is not supported yet"); 831 /** 832 return new ARMCOFFLDBackend(createARMCOFFArchiveReader, 833 createARMCOFFObjectReader, 834 createARMCOFFObjectWriter); 835 **/ 836 } 837 return new ARMGNULDBackend(pConfig, 838 new ARMGNUInfo(pConfig.targets().triple())); 839} 840 841} // namespace mcld 842 843//===----------------------------------------------------------------------===// 844// Force static initialization. 845//===----------------------------------------------------------------------===// 846extern "C" void MCLDInitializeARMLDBackend() { 847 // Register the linker backend 848 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheARMTarget, 849 mcld::createARMLDBackend); 850 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheThumbTarget, 851 mcld::createARMLDBackend); 852} 853