ARMLDBackend.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
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 <llvm/ADT/Triple.h> 10#include <llvm/ADT/Twine.h> 11#include <llvm/Support/ELF.h> 12#include <llvm/Support/ErrorHandling.h> 13 14#include <mcld/LD/SectionMap.h> 15#include <mcld/MC/MCLDInfo.h> 16#include <mcld/MC/MCLDOutput.h> 17#include <mcld/MC/MCLinker.h> 18#include <mcld/MC/MCRegionFragment.h> 19#include <mcld/Support/MemoryRegion.h> 20#include <mcld/Support/TargetRegistry.h> 21 22#include <cstring> 23 24#include "ARM.h" 25#include "ARMELFDynamic.h" 26#include "ARMLDBackend.h" 27#include "ARMRelocationFactory.h" 28 29using namespace mcld; 30 31ARMGNULDBackend::ARMGNULDBackend() 32 : m_pRelocFactory(NULL), 33 m_pGOT(NULL), 34 m_pPLT(NULL), 35 m_pRelDyn(NULL), 36 m_pRelPLT(NULL), 37 m_pDynamic(NULL), 38 m_pEXIDX(NULL), 39 m_pEXTAB(NULL), 40 m_pAttributes(NULL) { 41} 42 43ARMGNULDBackend::~ARMGNULDBackend() 44{ 45 if (m_pRelocFactory) 46 delete m_pRelocFactory; 47 if(m_pGOT) 48 delete m_pGOT; 49 if(m_pPLT) 50 delete m_pPLT; 51 if(m_pRelDyn) 52 delete m_pRelDyn; 53 if(m_pRelPLT) 54 delete m_pRelPLT; 55 if(m_pDynamic) 56 delete m_pDynamic; 57} 58 59bool ARMGNULDBackend::initRelocFactory(const MCLinker& pLinker) 60{ 61 if (NULL == m_pRelocFactory) { 62 m_pRelocFactory = new ARMRelocationFactory(1024, *this); 63 m_pRelocFactory->setLayout(pLinker.getLayout()); 64 } 65 return true; 66} 67 68RelocationFactory* ARMGNULDBackend::getRelocFactory() 69{ 70 assert(NULL != m_pRelocFactory); 71 return m_pRelocFactory; 72} 73 74bool ARMGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap) 75{ 76 if (!pSectionMap.push_back(".ARM.exidx", ".ARM.exidx") || 77 !pSectionMap.push_back(".ARM.extab", ".ARM.extab") || 78 !pSectionMap.push_back(".ARM.attributes", ".ARM.attributes")) 79 return false; 80 return true; 81} 82 83void ARMGNULDBackend::initTargetSections(MCLinker& pLinker) 84{ 85 // FIXME: Currently we set exidx and extab to "Exception" and directly emit 86 // them from input 87 m_pEXIDX = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx", 88 LDFileFormat::Exception, 89 llvm::ELF::SHT_ARM_EXIDX, 90 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER, 91 bitclass() / 8); 92 m_pEXTAB = &pLinker.getOrCreateOutputSectHdr(".ARM.extab", 93 LDFileFormat::Exception, 94 llvm::ELF::SHT_PROGBITS, 95 llvm::ELF::SHF_ALLOC, 96 0x1); 97 m_pAttributes = &pLinker.getOrCreateOutputSectHdr(".ARM.attributes", 98 LDFileFormat::Target, 99 llvm::ELF::SHT_ARM_ATTRIBUTES, 100 0x0, 101 0x1); 102} 103 104void ARMGNULDBackend::initTargetSymbols(MCLinker& pLinker) 105{ 106 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the 107 // same name in input 108 m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>( 109 "_GLOBAL_OFFSET_TABLE_", 110 false, 111 ResolveInfo::Object, 112 ResolveInfo::Define, 113 ResolveInfo::Local, 114 0x0, // size 115 0x0, // value 116 NULL, // FragRef 117 ResolveInfo::Hidden); 118} 119 120void ARMGNULDBackend::doPreLayout(const Output& pOutput, 121 const MCLDInfo& pInfo, 122 MCLinker& pLinker) 123{ 124 // when building shared object, the .got section is must. 125 if(pOutput.type() == Output::DynObj && (NULL == m_pGOT)) { 126 createARMGOT(pLinker, pOutput); 127 } 128} 129 130void ARMGNULDBackend::doPostLayout(const Output& pOutput, 131 const MCLDInfo& pInfo, 132 MCLinker& pLinker) 133{ 134 // emit program headers 135 if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) 136 emitProgramHdrs(pLinker.getLDInfo().output()); 137 138 ELFFileFormat *file_format = getOutputFormat(pOutput); 139 140 // apply PLT 141 if (file_format->hasPLT()) { 142 // Since we already have the size of LDSection PLT, m_pPLT should not be 143 // NULL. 144 assert(NULL != m_pPLT); 145 m_pPLT->applyPLT0(); 146 m_pPLT->applyPLT1(); 147 } 148 149 // apply GOT 150 if (file_format->hasGOT()) { 151 // Since we already have the size of GOT, m_pGOT should not be NULL. 152 assert(NULL != m_pGOT); 153 if (pOutput.type() == Output::DynObj) 154 m_pGOT->applyGOT0(file_format->getDynamic().addr()); 155 else { 156 // executable file and object file? should fill with zero. 157 m_pGOT->applyGOT0(0); 158 } 159 } 160} 161 162/// dynamic - the dynamic section of the target machine. 163/// Use co-variant return type to return its own dynamic section. 164ARMELFDynamic& ARMGNULDBackend::dynamic() 165{ 166 if (NULL == m_pDynamic) 167 m_pDynamic = new ARMELFDynamic(*this); 168 169 return *m_pDynamic; 170} 171 172/// dynamic - the dynamic section of the target machine. 173/// Use co-variant return type to return its own dynamic section. 174const ARMELFDynamic& ARMGNULDBackend::dynamic() const 175{ 176 assert( NULL != m_pDynamic); 177 return *m_pDynamic; 178} 179 180bool ARMGNULDBackend::isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const 181{ 182 return (pOutput.type() == Output::DynObj); 183} 184 185void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput) 186{ 187 // get .got LDSection and create MCSectionData 188 ELFFileFormat* file_format = getOutputFormat(pOutput); 189 190 LDSection& got = file_format->getGOT(); 191 m_pGOT = new ARMGOT(got, pLinker.getOrCreateSectData(got)); 192 193 // define symbol _GLOBAL_OFFSET_TABLE_ when .got create 194 if( m_pGOTSymbol != NULL ) { 195 pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>( 196 "_GLOBAL_OFFSET_TABLE_", 197 false, 198 ResolveInfo::Object, 199 ResolveInfo::Define, 200 ResolveInfo::Local, 201 0x0, // size 202 0x0, // value 203 pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0), 204 ResolveInfo::Hidden); 205 } 206 else { 207 m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>( 208 "_GLOBAL_OFFSET_TABLE_", 209 false, 210 ResolveInfo::Object, 211 ResolveInfo::Define, 212 ResolveInfo::Local, 213 0x0, // size 214 0x0, // value 215 pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0), 216 ResolveInfo::Hidden); 217 } 218 219} 220 221void ARMGNULDBackend::createARMPLTandRelPLT(MCLinker& pLinker, 222 const Output& pOutput) 223{ 224 ELFFileFormat* file_format = getOutputFormat(pOutput); 225 226 // get .plt and .rel.plt LDSection 227 LDSection& plt = file_format->getPLT(); 228 LDSection& relplt = file_format->getRelPlt(); 229 // create MCSectionData and ARMPLT 230 m_pPLT = new ARMPLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT); 231 // set info of .rel.plt to .plt 232 relplt.setLink(&plt); 233 // create MCSectionData and ARMRelDynSection 234 m_pRelPLT = new OutputRelocSection(relplt, 235 pLinker.getOrCreateSectData(relplt), 236 8); 237} 238 239void ARMGNULDBackend::createARMRelDyn(MCLinker& pLinker, 240 const Output& pOutput) 241{ 242 ELFFileFormat* file_format = getOutputFormat(pOutput); 243 244 // get .rel.dyn LDSection and create MCSectionData 245 LDSection& reldyn = file_format->getRelDyn(); 246 // create MCSectionData and ARMRelDynSection 247 m_pRelDyn = new OutputRelocSection(reldyn, 248 pLinker.getOrCreateSectData(reldyn), 249 8); 250} 251 252ELFFileFormat* ARMGNULDBackend::getOutputFormat(const Output& pOutput) const 253{ 254 switch (pOutput.type()) { 255 case Output::DynObj: 256 return getDynObjFileFormat(); 257 case Output::Exec: 258 return getExecFileFormat(); 259 // FIXME: We do not support building .o now 260 case Output::Object: 261 default: 262 llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") + 263 llvm::Twine(pOutput.type())); 264 return NULL; 265 } 266} 267 268bool ARMGNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym, 269 const MCLDInfo& pLDInfo, 270 const Output& pOutput) const 271{ 272 return (Output::DynObj == pOutput.type() && 273 ResolveInfo::Function == pSym.type() && 274 (pSym.isDyn() || pSym.isUndef() || 275 isSymbolPreemptible(pSym, pLDInfo, pOutput))); 276} 277 278bool ARMGNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym, 279 const Output& pOutput, 280 bool isAbsReloc) const 281{ 282 if(pSym.isUndef() && (Output::Exec == pOutput.type())) 283 return false; 284 if(pSym.isAbsolute()) 285 return false; 286 if(Output::DynObj == pOutput.type() && isAbsReloc) 287 return true; 288 if(pSym.isDyn() || pSym.isUndef()) 289 return true; 290 291 return false; 292} 293 294bool ARMGNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym, 295 const MCLDInfo& pLDInfo, 296 const Output& pOutput) const 297{ 298 if(pSym.other() != ResolveInfo::Default) 299 return false; 300 301 if(Output::DynObj != pOutput.type()) 302 return false; 303 304 if(pLDInfo.options().Bsymbolic()) 305 return false; 306 307 return true; 308} 309 310/// checkValidReloc - When we attempt to generate a dynamic relocation for 311/// ouput file, check if the relocation is supported by dynamic linker. 312void ARMGNULDBackend::checkValidReloc(Relocation& pReloc, 313 const MCLDInfo& pLDInfo, 314 const Output& pOutput) const 315{ 316 // If not building a PIC object, no relocation type is invalid 317 if (!isPIC(pLDInfo, pOutput)) 318 return; 319 320 switch(pReloc.type()) { 321 case llvm::ELF::R_ARM_RELATIVE: 322 case llvm::ELF::R_ARM_COPY: 323 case llvm::ELF::R_ARM_GLOB_DAT: 324 case llvm::ELF::R_ARM_JUMP_SLOT: 325 case llvm::ELF::R_ARM_ABS32: 326 case llvm::ELF::R_ARM_ABS32_NOI: 327 case llvm::ELF::R_ARM_PC24: 328 case llvm::ELF::R_ARM_TLS_DTPMOD32: 329 case llvm::ELF::R_ARM_TLS_DTPOFF32: 330 case llvm::ELF::R_ARM_TLS_TPOFF32: 331 break; 332 333 default: 334 llvm::report_fatal_error(llvm::Twine("Attempt to generate unsupported") + 335 llvm::Twine(" relocation type ") + 336 llvm::Twine((int)pReloc.type()) + 337 llvm::Twine(" for symbol '") + 338 llvm::Twine(pReloc.symInfo()->name()) + 339 llvm::Twine("', recompile with -fPIC") 340 ); 341 break; 342 } 343} 344 345void ARMGNULDBackend::updateAddend(Relocation& pReloc, 346 const LDSymbol& pInputSym, 347 const Layout& pLayout) const 348{ 349 // Update value keep in addend if we meet a section symbol 350 if(pReloc.symInfo()->type() == ResolveInfo::Section) { 351 pReloc.setAddend(pLayout.getOutputOffset( 352 *pInputSym.fragRef()) + pReloc.addend()); 353 } 354} 355 356void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc, 357 const LDSymbol& pInputSym, 358 MCLinker& pLinker, 359 const MCLDInfo& pLDInfo, 360 const Output& pOutput) 361{ 362 // rsym - The relocation target symbol 363 ResolveInfo* rsym = pReloc.symInfo(); 364 365 updateAddend(pReloc, pInputSym, pLinker.getLayout()); 366 367 switch(pReloc.type()){ 368 369 // Set R_ARM_TARGET1 to R_ARM_ABS32 370 // Ref: GNU gold 1.11 arm.cc, line 9892 371 case llvm::ELF::R_ARM_TARGET1: 372 pReloc.setType(llvm::ELF::R_ARM_ABS32); 373 case llvm::ELF::R_ARM_ABS32: 374 case llvm::ELF::R_ARM_ABS32_NOI: { 375 // If buiding PIC object (shared library or PIC executable), 376 // a dynamic relocations with RELATIVE type to this location is needed. 377 // Reserve an entry in .rel.dyn 378 if(isPIC(pLDInfo, pOutput)) { 379 // create .rel.dyn section if not exist 380 if(NULL == m_pRelDyn) 381 createARMRelDyn(pLinker, pOutput); 382 m_pRelDyn->reserveEntry(*m_pRelocFactory); 383 // set Rel bit 384 rsym->setReserved(rsym->reserved() | 0x1u); 385 } 386 return; 387 } 388 389 case llvm::ELF::R_ARM_ABS16: 390 case llvm::ELF::R_ARM_ABS12: 391 case llvm::ELF::R_ARM_THM_ABS5: 392 case llvm::ELF::R_ARM_ABS8: 393 case llvm::ELF::R_ARM_BASE_ABS: 394 case llvm::ELF::R_ARM_MOVW_ABS_NC: 395 case llvm::ELF::R_ARM_MOVT_ABS: 396 case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: 397 case llvm::ELF::R_ARM_THM_MOVT_ABS: { 398 // Update value keep in relocation place if we meet a section symbol 399 if(rsym->type() == ResolveInfo::Section) { 400 pReloc.target() = pLinker.getLayout().getOutputOffset( 401 *pInputSym.fragRef()) + pReloc.target(); 402 } 403 404 // If building PIC object (shared library or PIC executable), 405 // a dynamic relocation for this location is needed. 406 // Reserve an entry in .rel.dyn 407 if(isPIC(pLDInfo, pOutput)) { 408 checkValidReloc(pReloc, pLDInfo, pOutput); 409 // create .rel.dyn section if not exist 410 if(NULL == m_pRelDyn) 411 createARMRelDyn(pLinker, pOutput); 412 m_pRelDyn->reserveEntry(*m_pRelocFactory); 413 // set Rel bit 414 rsym->setReserved(rsym->reserved() | 0x1u); 415 } 416 return; 417 } 418 case llvm::ELF::R_ARM_GOTOFF32: 419 case llvm::ELF::R_ARM_GOTOFF12: { 420 // A GOT section is needed 421 if(NULL == m_pGOT) 422 createARMGOT(pLinker, pOutput); 423 return; 424 } 425 426 // Set R_ARM_TARGET2 to R_ARM_GOT_PREL 427 // Ref: GNU gold 1.11 arm.cc, line 9892 428 case llvm::ELF::R_ARM_TARGET2: 429 pReloc.setType(llvm::ELF::R_ARM_GOT_PREL); 430 case llvm::ELF::R_ARM_GOT_BREL: 431 case llvm::ELF::R_ARM_GOT_PREL: { 432 // A GOT entry is needed for these relocation type. 433 // return if we already create GOT for this symbol 434 if(rsym->reserved() & 0x6u) 435 return; 436 if(NULL == m_pGOT) 437 createARMGOT(pLinker, pOutput); 438 m_pGOT->reserveEntry(); 439 // If building PIC object, a dynamic relocation with 440 // type RELATIVE is needed to relocate this GOT entry. 441 // Reserve an entry in .rel.dyn 442 if(isPIC(pLDInfo, pOutput)) { 443 // create .rel.dyn section if not exist 444 if(NULL == m_pRelDyn) 445 createARMRelDyn(pLinker, pOutput); 446 m_pRelDyn->reserveEntry(*m_pRelocFactory); 447 // set GOTRel bit 448 rsym->setReserved(rsym->reserved() | 0x4u); 449 return; 450 } 451 // set GOT bit 452 rsym->setReserved(rsym->reserved() | 0x2u); 453 return; 454 } 455 456 case llvm::ELF::R_ARM_BASE_PREL: { 457 // FIXME: Currently we only support R_ARM_BASE_PREL against 458 // symbol _GLOBAL_OFFSET_TABLE_ 459 if(rsym != m_pGOTSymbol->resolveInfo()) { 460 llvm::report_fatal_error(llvm::Twine("Do not support relocation '") + 461 llvm::Twine("R_ARM_BASE_PREL' against symbol '") + 462 llvm::Twine(rsym->name()) + 463 llvm::Twine(".'")); 464 } 465 return; 466 } 467 case llvm::ELF::R_ARM_COPY: 468 case llvm::ELF::R_ARM_GLOB_DAT: 469 case llvm::ELF::R_ARM_JUMP_SLOT: 470 case llvm::ELF::R_ARM_RELATIVE: { 471 // These are relocation type for dynamic linker, shold not 472 // appear in object file. 473 llvm::report_fatal_error(llvm::Twine("unexpected reloc ") + 474 llvm::Twine((int)pReloc.type()) + 475 llvm::Twine(" in object file")); 476 break; 477 } 478 default: { 479 break; 480 } 481 } // end switch 482} 483 484void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc, 485 const LDSymbol& pInputSym, 486 MCLinker& pLinker, 487 const MCLDInfo& pLDInfo, 488 const Output& pOutput) 489{ 490 // rsym - The relocation target symbol 491 ResolveInfo* rsym = pReloc.symInfo(); 492 493 switch(pReloc.type()) { 494 495 // Set R_ARM_TARGET1 to R_ARM_ABS32 496 // Ref: GNU gold 1.11 arm.cc, line 9892 497 case llvm::ELF::R_ARM_TARGET1: 498 pReloc.setType(llvm::ELF::R_ARM_ABS32); 499 case llvm::ELF::R_ARM_ABS32: 500 case llvm::ELF::R_ARM_ABS16: 501 case llvm::ELF::R_ARM_ABS12: 502 case llvm::ELF::R_ARM_THM_ABS5: 503 case llvm::ELF::R_ARM_ABS8: 504 case llvm::ELF::R_ARM_BASE_ABS: 505 case llvm::ELF::R_ARM_MOVW_ABS_NC: 506 case llvm::ELF::R_ARM_MOVT_ABS: 507 case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: 508 case llvm::ELF::R_ARM_THM_MOVT_ABS: 509 case llvm::ELF::R_ARM_ABS32_NOI: { 510 // Absolute relocation type, symbol may needs PLT entry or 511 // dynamic relocation entry 512 if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) { 513 // create plt for this symbol if it does not have one 514 if(!(rsym->reserved() & 0x8u)){ 515 // Create .got section if it doesn't exist 516 if(NULL == m_pGOT) 517 createARMGOT(pLinker, pOutput); 518 // create .plt and .rel.plt if not exist 519 if(NULL == m_pPLT) 520 createARMPLTandRelPLT(pLinker, pOutput); 521 // Symbol needs PLT entry, we need to reserve a PLT entry 522 // and the corresponding GOT and dynamic relocation entry 523 // in .got and .rel.plt. (GOT entry will be reserved simultaneously 524 // when calling ARMPLT->reserveEntry()) 525 m_pPLT->reserveEntry(); 526 m_pRelPLT->reserveEntry(*m_pRelocFactory); 527 // set PLT bit 528 rsym->setReserved(rsym->reserved() | 0x8u); 529 } 530 } 531 532 if(isSymbolNeedsDynRel(*rsym, pOutput, true)) { 533 checkValidReloc(pReloc, pLDInfo, pOutput); 534 // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 535 // create .rel.dyn section if not exist 536 if(NULL == m_pRelDyn) 537 createARMRelDyn(pLinker, pOutput); 538 m_pRelDyn->reserveEntry(*m_pRelocFactory); 539 // set Rel bit 540 rsym->setReserved(rsym->reserved() | 0x1u); 541 } 542 return; 543 } 544 545 case llvm::ELF::R_ARM_GOTOFF32: 546 case llvm::ELF::R_ARM_GOTOFF12: { 547 // A GOT section is needed 548 if(NULL == m_pGOT) 549 createARMGOT(pLinker, pOutput); 550 return; 551 } 552 553 case llvm::ELF::R_ARM_BASE_PREL: 554 // FIXME: Currently we only support R_ARM_BASE_PREL against 555 // symbol _GLOBAL_OFFSET_TABLE_ 556 if(rsym != m_pGOTSymbol->resolveInfo()) { 557 llvm::report_fatal_error(llvm::Twine("Do not support relocation '") + 558 llvm::Twine("R_ARM_BASE_PREL' against symbol '") + 559 llvm::Twine(rsym->name()) + 560 llvm::Twine(".'")); 561 } 562 case llvm::ELF::R_ARM_REL32: 563 case llvm::ELF::R_ARM_LDR_PC_G0: 564 case llvm::ELF::R_ARM_SBREL32: 565 case llvm::ELF::R_ARM_THM_PC8: 566 case llvm::ELF::R_ARM_MOVW_PREL_NC: 567 case llvm::ELF::R_ARM_MOVT_PREL: 568 case llvm::ELF::R_ARM_THM_MOVW_PREL_NC: 569 case llvm::ELF::R_ARM_THM_MOVT_PREL: 570 case llvm::ELF::R_ARM_THM_ALU_PREL_11_0: 571 case llvm::ELF::R_ARM_THM_PC12: 572 case llvm::ELF::R_ARM_REL32_NOI: 573 case llvm::ELF::R_ARM_ALU_PC_G0_NC: 574 case llvm::ELF::R_ARM_ALU_PC_G0: 575 case llvm::ELF::R_ARM_ALU_PC_G1_NC: 576 case llvm::ELF::R_ARM_ALU_PC_G1: 577 case llvm::ELF::R_ARM_ALU_PC_G2: 578 case llvm::ELF::R_ARM_LDR_PC_G1: 579 case llvm::ELF::R_ARM_LDR_PC_G2: 580 case llvm::ELF::R_ARM_LDRS_PC_G0: 581 case llvm::ELF::R_ARM_LDRS_PC_G1: 582 case llvm::ELF::R_ARM_LDRS_PC_G2: 583 case llvm::ELF::R_ARM_LDC_PC_G0: 584 case llvm::ELF::R_ARM_LDC_PC_G1: 585 case llvm::ELF::R_ARM_LDC_PC_G2: 586 case llvm::ELF::R_ARM_ALU_SB_G0_NC: 587 case llvm::ELF::R_ARM_ALU_SB_G0: 588 case llvm::ELF::R_ARM_ALU_SB_G1_NC: 589 case llvm::ELF::R_ARM_ALU_SB_G1: 590 case llvm::ELF::R_ARM_ALU_SB_G2: 591 case llvm::ELF::R_ARM_LDR_SB_G0: 592 case llvm::ELF::R_ARM_LDR_SB_G1: 593 case llvm::ELF::R_ARM_LDR_SB_G2: 594 case llvm::ELF::R_ARM_LDRS_SB_G0: 595 case llvm::ELF::R_ARM_LDRS_SB_G1: 596 case llvm::ELF::R_ARM_LDRS_SB_G2: 597 case llvm::ELF::R_ARM_LDC_SB_G0: 598 case llvm::ELF::R_ARM_LDC_SB_G1: 599 case llvm::ELF::R_ARM_LDC_SB_G2: 600 case llvm::ELF::R_ARM_MOVW_BREL_NC: 601 case llvm::ELF::R_ARM_MOVT_BREL: 602 case llvm::ELF::R_ARM_MOVW_BREL: 603 case llvm::ELF::R_ARM_THM_MOVW_BREL_NC: 604 case llvm::ELF::R_ARM_THM_MOVT_BREL: 605 case llvm::ELF::R_ARM_THM_MOVW_BREL: { 606 // Relative addressing relocation, may needs dynamic relocation 607 if(isSymbolNeedsDynRel(*rsym, pOutput, false)) { 608 checkValidReloc(pReloc, pLDInfo, pOutput); 609 // create .rel.dyn section if not exist 610 if(NULL == m_pRelDyn) 611 createARMRelDyn(pLinker, pOutput); 612 m_pRelDyn->reserveEntry(*m_pRelocFactory); 613 // set Rel bit 614 rsym->setReserved(rsym->reserved() | 0x1u); 615 } 616 return; 617 } 618 619 case llvm::ELF::R_ARM_THM_CALL: 620 case llvm::ELF::R_ARM_PLT32: 621 case llvm::ELF::R_ARM_CALL: 622 case llvm::ELF::R_ARM_JUMP24: 623 case llvm::ELF::R_ARM_THM_JUMP24: 624 case llvm::ELF::R_ARM_SBREL31: 625 case llvm::ELF::R_ARM_PREL31: 626 case llvm::ELF::R_ARM_THM_JUMP19: 627 case llvm::ELF::R_ARM_THM_JUMP6: 628 case llvm::ELF::R_ARM_THM_JUMP11: 629 case llvm::ELF::R_ARM_THM_JUMP8: { 630 // These are branch relocation (except PREL31) 631 // A PLT entry is needed when building shared library 632 633 // return if we already create plt for this symbol 634 if(rsym->reserved() & 0x8u) 635 return; 636 637 // if symbol is defined in the ouput file and it's not 638 // preemptible, no need plt 639 if(rsym->isDefine() && !rsym->isDyn() && 640 !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) { 641 return; 642 } 643 644 // Create .got section if it doesn't exist 645 if(NULL == m_pGOT) 646 createARMGOT(pLinker, pOutput); 647 648 // create .plt and .rel.plt if not exist 649 if(NULL == m_pPLT) 650 createARMPLTandRelPLT(pLinker, pOutput); 651 // Symbol needs PLT entry, we need to reserve a PLT entry 652 // and the corresponding GOT and dynamic relocation entry 653 // in .got and .rel.plt. (GOT entry will be reserved simultaneously 654 // when calling ARMPLT->reserveEntry()) 655 m_pPLT->reserveEntry(); 656 m_pRelPLT->reserveEntry(*m_pRelocFactory); 657 // set PLT bit 658 rsym->setReserved(rsym->reserved() | 0x8u); 659 return; 660 } 661 662 // Set R_ARM_TARGET2 to R_ARM_GOT_PREL 663 // Ref: GNU gold 1.11 arm.cc, line 9892 664 case llvm::ELF::R_ARM_TARGET2: 665 pReloc.setType(llvm::ELF::R_ARM_GOT_PREL); 666 case llvm::ELF::R_ARM_GOT_BREL: 667 case llvm::ELF::R_ARM_GOT_ABS: 668 case llvm::ELF::R_ARM_GOT_PREL: { 669 // Symbol needs GOT entry, reserve entry in .got 670 // return if we already create GOT for this symbol 671 if(rsym->reserved() & 0x6u) 672 return; 673 if(NULL == m_pGOT) 674 createARMGOT(pLinker, pOutput); 675 m_pGOT->reserveEntry(); 676 // If building shared object or the symbol is undefined, a dynamic 677 // relocation is needed to relocate this GOT entry. Reserve an 678 // entry in .rel.dyn 679 if(Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) { 680 // create .rel.dyn section if not exist 681 if(NULL == m_pRelDyn) 682 createARMRelDyn(pLinker, pOutput); 683 m_pRelDyn->reserveEntry(*m_pRelocFactory); 684 // set GOTRel bit 685 rsym->setReserved(rsym->reserved() | 0x4u); 686 return; 687 } 688 // set GOT bit 689 rsym->setReserved(rsym->reserved() | 0x2u); 690 return; 691 } 692 693 case llvm::ELF::R_ARM_COPY: 694 case llvm::ELF::R_ARM_GLOB_DAT: 695 case llvm::ELF::R_ARM_JUMP_SLOT: 696 case llvm::ELF::R_ARM_RELATIVE: { 697 // These are relocation type for dynamic linker, shold not 698 // appear in object file. 699 llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") + 700 llvm::Twine((int)pReloc.type()) + 701 llvm::Twine(" in object file")); 702 break; 703 } 704 default: { 705 break; 706 } 707 } // end switch 708} 709 710void ARMGNULDBackend::scanRelocation(Relocation& pReloc, 711 const LDSymbol& pInputSym, 712 MCLinker& pLinker, 713 const MCLDInfo& pLDInfo, 714 const Output& pOutput) 715{ 716 // rsym - The relocation target symbol 717 ResolveInfo* rsym = pReloc.symInfo(); 718 assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation"); 719 720 // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation 721 // entries should be created. 722 // FIXME: Below judgements concern only .so is generated as output 723 // FIXME: Below judgements concern nothing about TLS related relocation 724 725 // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section 726 // is needed 727 if(NULL == m_pGOT && NULL != m_pGOTSymbol) { 728 if(rsym == m_pGOTSymbol->resolveInfo()) { 729 createARMGOT(pLinker, pOutput); 730 } 731 } 732 733 // rsym is local 734 if(rsym->isLocal()) 735 scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput); 736 737 // rsym is external 738 else 739 scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput); 740 741} 742 743uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput, 744 const LDSection& pSection, 745 const MCLDInfo& pInfo, 746 MemoryRegion& pRegion) const 747{ 748 assert(pRegion.size() && "Size of MemoryRegion is zero!"); 749 750 ELFFileFormat* file_format = getOutputFormat(pOutput); 751 752 if (&pSection == m_pAttributes) { 753 // FIXME: Currently Emitting .ARM.attributes directly from the input file. 754 const llvm::MCSectionData* sect_data = pSection.getSectionData(); 755 assert(sect_data && 756 "Emit .ARM.attribute failed, MCSectionData doesn't exist!"); 757 758 uint8_t* start = 759 llvm::cast<MCRegionFragment>( 760 sect_data->getFragmentList().front()).getRegion().start(); 761 762 memcpy(pRegion.start(), start, pRegion.size()); 763 return pRegion.size(); 764 } 765 766 if (&pSection == &(file_format->getPLT())) { 767 assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!"); 768 uint64_t result = m_pPLT->emit(pRegion); 769 return result; 770 } 771 772 if (&pSection == &(file_format->getGOT())) { 773 assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!"); 774 uint64_t result = m_pGOT->emit(pRegion); 775 return result; 776 } 777 778 llvm::report_fatal_error(llvm::Twine("Unable to emit section `") + 779 pSection.name() + 780 llvm::Twine("'.\n")); 781 return 0x0; 782} 783 784/// finalizeSymbol - finalize the symbol value 785/// If the symbol's reserved field is not zero, MCLinker will call back this 786/// function to ask the final value of the symbol 787bool ARMGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const 788{ 789 return false; 790} 791 792/// allocateCommonSymbols - allocate common symbols in the corresponding 793/// sections. 794/// @refer Google gold linker: common.cc: 214 795bool 796ARMGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const 797{ 798 SymbolCategory& symbol_list = pLinker.getOutputSymbols(); 799 800 if (symbol_list.emptyCommons() && symbol_list.emptyLocals()) 801 return true; 802 803 // addralign := max value of all common symbols 804 uint64_t addralign = 0x0; 805 806 // Due to the visibility, some common symbols may be forcefully local. 807 SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd(); 808 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) { 809 if (ResolveInfo::Common == (*com_sym)->desc()) { 810 if ((*com_sym)->value() > addralign) 811 addralign = (*com_sym)->value(); 812 } 813 } 814 815 // global common symbols. 816 com_end = symbol_list.commonEnd(); 817 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) { 818 if ((*com_sym)->value() > addralign) 819 addralign = (*com_sym)->value(); 820 } 821 822 // FIXME: If the order of common symbols is defined, then sort common symbols 823 // com_sym = symbol_list.commonBegin(); 824 // std::sort(com_sym, com_end, some kind of order); 825 826 // get or create corresponding BSS LDSection 827 LDSection* bss_sect_hdr = NULL; 828 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) { 829 bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr( 830 ".tbss", 831 LDFileFormat::BSS, 832 llvm::ELF::SHT_NOBITS, 833 llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC); 834 } 835 else { 836 bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss", 837 LDFileFormat::BSS, 838 llvm::ELF::SHT_NOBITS, 839 llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC); 840 } 841 842 // get or create corresponding BSS MCSectionData 843 assert(NULL != bss_sect_hdr); 844 llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr); 845 846 // allocate all common symbols 847 uint64_t offset = bss_sect_hdr->size(); 848 849 // allocate all local common symbols 850 com_end = symbol_list.localEnd(); 851 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) { 852 if (ResolveInfo::Common == (*com_sym)->desc()) { 853 // We have to reset the description of the symbol here. When doing 854 // incremental linking, the output relocatable object may have common 855 // symbols. Therefore, we can not treat common symbols as normal symbols 856 // when emitting the regular name pools. We must change the symbols' 857 // description here. 858 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define); 859 llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size()); 860 (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0)); 861 uint64_t size = pLinker.getLayout().appendFragment(*frag, 862 bss_section, 863 (*com_sym)->value()); 864 offset += size; 865 } 866 } 867 868 // allocate all global common symbols 869 com_end = symbol_list.commonEnd(); 870 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) { 871 // We have to reset the description of the symbol here. When doing 872 // incremental linking, the output relocatable object may have common 873 // symbols. Therefore, we can not treat common symbols as normal symbols 874 // when emitting the regular name pools. We must change the symbols' 875 // description here. 876 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define); 877 llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size()); 878 (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0)); 879 uint64_t size = pLinker.getLayout().appendFragment(*frag, 880 bss_section, 881 (*com_sym)->value()); 882 offset += size; 883 } 884 885 bss_sect_hdr->setSize(offset); 886 symbol_list.changeCommonsToGlobal(); 887 return true; 888} 889 890bool ARMGNULDBackend::readSection(Input& pInput, 891 MCLinker& pLinker, 892 LDSection& pInputSectHdr) 893{ 894 LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(), 895 pInputSectHdr.kind(), 896 pInputSectHdr.type(), 897 pInputSectHdr.flag()); 898 // FIXME: (Luba) 899 // Handle ARM attributes in the right way. 900 // In current milestone, MCLinker goes through the shortcut. 901 // It reads input's ARM attributes and copies the first ARM attributes 902 // into the output file. The correct way is merge these sections, not 903 // just copy. 904 if ((0 == out_sect.name().compare(".ARM.attributes")) && 905 (0 != out_sect.size())) 906 return true; 907 908 MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(), 909 pInputSectHdr.size()); 910 911 llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr); 912 913 new MCRegionFragment(*region, §_data); 914 915 out_sect.setSize(out_sect.size() + pInputSectHdr.size()); 916 return true; 917} 918 919ARMGOT& ARMGNULDBackend::getGOT() 920{ 921 assert(NULL != m_pGOT && "GOT section not exist"); 922 return *m_pGOT; 923} 924 925const ARMGOT& ARMGNULDBackend::getGOT() const 926{ 927 assert(NULL != m_pGOT && "GOT section not exist"); 928 return *m_pGOT; 929} 930 931ARMPLT& ARMGNULDBackend::getPLT() 932{ 933 assert(NULL != m_pPLT && "PLT section not exist"); 934 return *m_pPLT; 935} 936 937const ARMPLT& ARMGNULDBackend::getPLT() const 938{ 939 assert(NULL != m_pPLT && "PLT section not exist"); 940 return *m_pPLT; 941} 942 943OutputRelocSection& ARMGNULDBackend::getRelDyn() 944{ 945 assert(NULL != m_pRelDyn && ".rel.dyn section not exist"); 946 return *m_pRelDyn; 947} 948 949const OutputRelocSection& ARMGNULDBackend::getRelDyn() const 950{ 951 assert(NULL != m_pRelDyn && ".rel.dyn section not exist"); 952 return *m_pRelDyn; 953} 954 955OutputRelocSection& ARMGNULDBackend::getRelPLT() 956{ 957 assert(NULL != m_pRelPLT && ".rel.plt section not exist"); 958 return *m_pRelPLT; 959} 960 961const OutputRelocSection& ARMGNULDBackend::getRelPLT() const 962{ 963 assert(NULL != m_pRelPLT && ".rel.plt section not exist"); 964 return *m_pRelPLT; 965} 966 967unsigned int 968ARMGNULDBackend::getTargetSectionOrder(const Output& pOutput, 969 const LDSection& pSectHdr) const 970{ 971 ELFFileFormat* file_format = getOutputFormat(pOutput); 972 973 if (&pSectHdr == &file_format->getGOT()) 974 return SHO_DATA; 975 976 if (&pSectHdr == &file_format->getPLT()) 977 return SHO_PLT; 978 979 return SHO_UNDEFINED; 980} 981 982namespace mcld { 983 984//===----------------------------------------------------------------------===// 985/// createARMLDBackend - the help funtion to create corresponding ARMLDBackend 986/// 987TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget, 988 const std::string& pTriple) 989{ 990 Triple theTriple(pTriple); 991 if (theTriple.isOSDarwin()) { 992 assert(0 && "MachO linker is not supported yet"); 993 /** 994 return new ARMMachOLDBackend(createARMMachOArchiveReader, 995 createARMMachOObjectReader, 996 createARMMachOObjectWriter); 997 **/ 998 } 999 if (theTriple.isOSWindows()) { 1000 assert(0 && "COFF linker is not supported yet"); 1001 /** 1002 return new ARMCOFFLDBackend(createARMCOFFArchiveReader, 1003 createARMCOFFObjectReader, 1004 createARMCOFFObjectWriter); 1005 **/ 1006 } 1007 return new ARMGNULDBackend(); 1008} 1009 1010} // namespace of mcld 1011 1012//============================= 1013// Force static initialization. 1014extern "C" void LLVMInitializeARMLDBackend() { 1015 // Register the linker backend 1016 mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend); 1017} 1018 1019