ARMLDBackend.cpp revision affc150dc44fab1911775a49636d0ce85333b634
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 13#include <mcld/LD/SectionMap.h> 14#include <mcld/MC/MCLDInfo.h> 15#include <mcld/MC/MCLDOutput.h> 16#include <mcld/MC/MCLinker.h> 17#include <mcld/MC/MCRegionFragment.h> 18#include <mcld/Support/MemoryRegion.h> 19#include <mcld/Support/MsgHandling.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 (NULL != m_pRelocFactory) 46 delete m_pRelocFactory; 47 if (NULL != m_pGOT) 48 delete m_pGOT; 49 if (NULL != m_pPLT) 50 delete m_pPLT; 51 if (NULL != m_pRelDyn) 52 delete m_pRelDyn; 53 if (NULL != m_pRelPLT) 54 delete m_pRelPLT; 55 if (NULL != 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::Target, 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::Target, 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, const Output& pOutput) 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 const ELFFileFormat *file_format = getOutputFormat(pOutput); 135 136 // apply PLT 137 if (file_format->hasPLT()) { 138 // Since we already have the size of LDSection PLT, m_pPLT should not be 139 // NULL. 140 assert(NULL != m_pPLT); 141 m_pPLT->applyPLT0(); 142 m_pPLT->applyPLT1(); 143 } 144 145 // apply GOT 146 if (file_format->hasGOT()) { 147 // Since we already have the size of GOT, m_pGOT should not be NULL. 148 assert(NULL != m_pGOT); 149 if (pOutput.type() == Output::DynObj) 150 m_pGOT->applyGOT0(file_format->getDynamic().addr()); 151 else { 152 // executable file and object file? should fill with zero. 153 m_pGOT->applyGOT0(0); 154 } 155 } 156} 157 158/// dynamic - the dynamic section of the target machine. 159/// Use co-variant return type to return its own dynamic section. 160ARMELFDynamic& ARMGNULDBackend::dynamic() 161{ 162 if (NULL == m_pDynamic) 163 m_pDynamic = new ARMELFDynamic(*this); 164 165 return *m_pDynamic; 166} 167 168/// dynamic - the dynamic section of the target machine. 169/// Use co-variant return type to return its own dynamic section. 170const ARMELFDynamic& ARMGNULDBackend::dynamic() const 171{ 172 assert( NULL != m_pDynamic); 173 return *m_pDynamic; 174} 175 176void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput) 177{ 178 // get .got LDSection and create MCSectionData 179 ELFFileFormat* file_format = getOutputFormat(pOutput); 180 181 LDSection& got = file_format->getGOT(); 182 m_pGOT = new ARMGOT(got, pLinker.getOrCreateSectData(got)); 183 184 // define symbol _GLOBAL_OFFSET_TABLE_ when .got create 185 if (m_pGOTSymbol != NULL) { 186 pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>( 187 "_GLOBAL_OFFSET_TABLE_", 188 false, 189 ResolveInfo::Object, 190 ResolveInfo::Define, 191 ResolveInfo::Local, 192 0x0, // size 193 0x0, // value 194 pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0), 195 ResolveInfo::Hidden); 196 } 197 else { 198 m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>( 199 "_GLOBAL_OFFSET_TABLE_", 200 false, 201 ResolveInfo::Object, 202 ResolveInfo::Define, 203 ResolveInfo::Local, 204 0x0, // size 205 0x0, // value 206 pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0), 207 ResolveInfo::Hidden); 208 } 209 210} 211 212void ARMGNULDBackend::createARMPLTandRelPLT(MCLinker& pLinker, 213 const Output& pOutput) 214{ 215 ELFFileFormat* file_format = getOutputFormat(pOutput); 216 217 // get .plt and .rel.plt LDSection 218 LDSection& plt = file_format->getPLT(); 219 LDSection& relplt = file_format->getRelPlt(); 220 // create MCSectionData and ARMPLT 221 m_pPLT = new ARMPLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT); 222 // set info of .rel.plt to .plt 223 relplt.setLink(&plt); 224 // create MCSectionData and ARMRelDynSection 225 m_pRelPLT = new OutputRelocSection(relplt, 226 pLinker.getOrCreateSectData(relplt), 227 8); 228} 229 230void ARMGNULDBackend::createARMRelDyn(MCLinker& pLinker, 231 const Output& pOutput) 232{ 233 ELFFileFormat* file_format = getOutputFormat(pOutput); 234 235 // get .rel.dyn LDSection and create MCSectionData 236 LDSection& reldyn = file_format->getRelDyn(); 237 // create MCSectionData and ARMRelDynSection 238 m_pRelDyn = new OutputRelocSection(reldyn, 239 pLinker.getOrCreateSectData(reldyn), 240 8); 241} 242 243void ARMGNULDBackend::addCopyReloc(ResolveInfo& pSym) 244{ 245 bool exist; 246 Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist); 247 rel_entry.setType(llvm::ELF::R_ARM_COPY); 248 assert(pSym.outSymbol()->hasFragRef()); 249 rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 250 rel_entry.setSymInfo(&pSym); 251} 252 253LDSymbol& ARMGNULDBackend::defineSymbolforCopyReloc(MCLinker& pLinker, 254 const ResolveInfo& pSym) 255{ 256 // For a symbol needing copy relocation, define a copy symbol in the BSS 257 // section and all other reference to this symbol should refer to this 258 // copy. 259 260 // get or create corresponding BSS LDSection 261 LDSection* bss_sect_hdr = NULL; 262 if (ResolveInfo::ThreadLocal == pSym.type()) { 263 bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr( 264 ".tbss", 265 LDFileFormat::BSS, 266 llvm::ELF::SHT_NOBITS, 267 llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC); 268 } 269 else { 270 bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss", 271 LDFileFormat::BSS, 272 llvm::ELF::SHT_NOBITS, 273 llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC); 274 } 275 276 // get or create corresponding BSS MCSectionData 277 assert(NULL != bss_sect_hdr); 278 llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData( 279 *bss_sect_hdr); 280 281 // Determine the alignment by the symbol value 282 // FIXME: here we use the largest alignment 283 uint32_t addralign = bitclass() / 8; 284 285 // allocate space in BSS for the copy symbol 286 llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, pSym.size()); 287 uint64_t size = pLinker.getLayout().appendFragment(*frag, 288 bss_section, 289 addralign); 290 bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 291 292 // change symbol binding to Global if it's a weak symbol 293 ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 294 if (binding == ResolveInfo::Weak) 295 binding = ResolveInfo::Global; 296 297 // Define the copy symbol in the bss section and resolve it 298 LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>( 299 pSym.name(), 300 false, 301 (ResolveInfo::Type)pSym.type(), 302 ResolveInfo::Define, 303 binding, 304 pSym.size(), // size 305 0x0, // value 306 pLinker.getLayout().getFragmentRef(*frag, 0x0), 307 (ResolveInfo::Visibility)pSym.other()); 308 309 return *cpy_sym; 310} 311 312/// checkValidReloc - When we attempt to generate a dynamic relocation for 313/// ouput file, check if the relocation is supported by dynamic linker. 314void ARMGNULDBackend::checkValidReloc(Relocation& pReloc, 315 const MCLDInfo& pLDInfo, 316 const Output& pOutput) const 317{ 318 // If not building a PIC object, no relocation type is invalid 319 if (!isOutputPIC(pOutput, pLDInfo)) 320 return; 321 322 switch(pReloc.type()) { 323 case llvm::ELF::R_ARM_RELATIVE: 324 case llvm::ELF::R_ARM_COPY: 325 case llvm::ELF::R_ARM_GLOB_DAT: 326 case llvm::ELF::R_ARM_JUMP_SLOT: 327 case llvm::ELF::R_ARM_ABS32: 328 case llvm::ELF::R_ARM_ABS32_NOI: 329 case llvm::ELF::R_ARM_PC24: 330 case llvm::ELF::R_ARM_TLS_DTPMOD32: 331 case llvm::ELF::R_ARM_TLS_DTPOFF32: 332 case llvm::ELF::R_ARM_TLS_TPOFF32: 333 break; 334 335 default: 336 error(diag::non_pic_relocation) << (int)pReloc.type() 337 << pReloc.symInfo()->name(); 338 break; 339 } 340} 341 342void ARMGNULDBackend::updateAddend(Relocation& pReloc, 343 const LDSymbol& pInputSym, 344 const Layout& pLayout) const 345{ 346 // Update value keep in addend if we meet a section symbol 347 if (pReloc.symInfo()->type() == ResolveInfo::Section) { 348 pReloc.setAddend(pLayout.getOutputOffset( 349 *pInputSym.fragRef()) + pReloc.addend()); 350 } 351} 352 353void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc, 354 const LDSymbol& pInputSym, 355 MCLinker& pLinker, 356 const MCLDInfo& pLDInfo, 357 const Output& pOutput) 358{ 359 // rsym - The relocation target symbol 360 ResolveInfo* rsym = pReloc.symInfo(); 361 362 updateAddend(pReloc, pInputSym, pLinker.getLayout()); 363 364 switch(pReloc.type()){ 365 366 // Set R_ARM_TARGET1 to R_ARM_ABS32 367 // Ref: GNU gold 1.11 arm.cc, line 9892 368 // FIXME: R_ARM_TARGET1 should be set by option --target1-rel 369 // or --target1-rel 370 case llvm::ELF::R_ARM_TARGET1: 371 pReloc.setType(llvm::ELF::R_ARM_ABS32); 372 case llvm::ELF::R_ARM_ABS32: 373 case llvm::ELF::R_ARM_ABS32_NOI: { 374 // If buiding PIC object (shared library or PIC executable), 375 // a dynamic relocations with RELATIVE type to this location is needed. 376 // Reserve an entry in .rel.dyn 377 if (isOutputPIC(pOutput, pLDInfo)) { 378 //create .rel.dyn section if not exist 379 if (NULL == m_pRelDyn) 380 createARMRelDyn(pLinker, pOutput); 381 m_pRelDyn->reserveEntry(*m_pRelocFactory); 382 // set Rel bit 383 rsym->setReserved(rsym->reserved() | ReserveRel); 384 } 385 return; 386 } 387 388 case llvm::ELF::R_ARM_ABS16: 389 case llvm::ELF::R_ARM_ABS12: 390 case llvm::ELF::R_ARM_THM_ABS5: 391 case llvm::ELF::R_ARM_ABS8: 392 case llvm::ELF::R_ARM_BASE_ABS: 393 case llvm::ELF::R_ARM_MOVW_ABS_NC: 394 case llvm::ELF::R_ARM_MOVT_ABS: 395 case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: 396 case llvm::ELF::R_ARM_THM_MOVT_ABS: { 397 // PIC code should not contain these kinds of relocation 398 if (isOutputPIC(pOutput, pLDInfo)) { 399 error(diag::non_pic_relocation) << (int)pReloc.type() 400 << pReloc.symInfo()->name(); 401 } 402 return; 403 } 404 case llvm::ELF::R_ARM_GOTOFF32: 405 case llvm::ELF::R_ARM_GOTOFF12: { 406 // A GOT section is needed 407 if (NULL == m_pGOT) 408 createARMGOT(pLinker, pOutput); 409 return; 410 } 411 412 // Set R_ARM_TARGET2 to R_ARM_GOT_PREL 413 // Ref: GNU gold 1.11 arm.cc, line 9892 414 // FIXME: R_ARM_TARGET2 should be set by option --target2 415 case llvm::ELF::R_ARM_TARGET2: 416 pReloc.setType(llvm::ELF::R_ARM_GOT_PREL); 417 case llvm::ELF::R_ARM_GOT_BREL: 418 case llvm::ELF::R_ARM_GOT_PREL: { 419 // A GOT entry is needed for these relocation type. 420 // return if we already create GOT for this symbol 421 if (rsym->reserved() & (ReserveGOT | GOTRel)) 422 return; 423 if (NULL == m_pGOT) 424 createARMGOT(pLinker, pOutput); 425 m_pGOT->reserveEntry(); 426 // If building PIC object, a dynamic relocation with 427 // type RELATIVE is needed to relocate this GOT entry. 428 // Reserve an entry in .rel.dyn 429 if (isOutputPIC(pOutput, pLDInfo)) { 430 // create .rel.dyn section if not exist 431 if (NULL == m_pRelDyn) 432 createARMRelDyn(pLinker, pOutput); 433 m_pRelDyn->reserveEntry(*m_pRelocFactory); 434 // set GOTRel bit 435 rsym->setReserved(rsym->reserved() | 0x4u); 436 return; 437 } 438 // set GOT bit 439 rsym->setReserved(rsym->reserved() | 0x2u); 440 return; 441 } 442 443 case llvm::ELF::R_ARM_BASE_PREL: { 444 // FIXME: Currently we only support R_ARM_BASE_PREL against 445 // symbol _GLOBAL_OFFSET_TABLE_ 446 if (rsym != m_pGOTSymbol->resolveInfo()) 447 fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name() 448 << "mclinker@googlegroups.com"; 449 return; 450 } 451 case llvm::ELF::R_ARM_COPY: 452 case llvm::ELF::R_ARM_GLOB_DAT: 453 case llvm::ELF::R_ARM_JUMP_SLOT: 454 case llvm::ELF::R_ARM_RELATIVE: { 455 // These are relocation type for dynamic linker, shold not 456 // appear in object file. 457 fatal(diag::dynamic_relocation) << (int)pReloc.type(); 458 break; 459 } 460 default: { 461 break; 462 } 463 } // end switch 464} 465 466void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc, 467 const LDSymbol& pInputSym, 468 MCLinker& pLinker, 469 const MCLDInfo& pLDInfo, 470 const Output& pOutput) 471{ 472 // rsym - The relocation target symbol 473 ResolveInfo* rsym = pReloc.symInfo(); 474 475 switch(pReloc.type()) { 476 477 // Set R_ARM_TARGET1 to R_ARM_ABS32 478 // Ref: GNU gold 1.11 arm.cc, line 9892 479 // FIXME: R_ARM_TARGET1 should be set by option --target1-rel 480 // or --target1-rel 481 case llvm::ELF::R_ARM_TARGET1: 482 pReloc.setType(llvm::ELF::R_ARM_ABS32); 483 case llvm::ELF::R_ARM_ABS32: 484 case llvm::ELF::R_ARM_ABS16: 485 case llvm::ELF::R_ARM_ABS12: 486 case llvm::ELF::R_ARM_THM_ABS5: 487 case llvm::ELF::R_ARM_ABS8: 488 case llvm::ELF::R_ARM_BASE_ABS: 489 case llvm::ELF::R_ARM_MOVW_ABS_NC: 490 case llvm::ELF::R_ARM_MOVT_ABS: 491 case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: 492 case llvm::ELF::R_ARM_THM_MOVT_ABS: 493 case llvm::ELF::R_ARM_ABS32_NOI: { 494 // Absolute relocation type, symbol may needs PLT entry or 495 // dynamic relocation entry 496 if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) { 497 // create plt for this symbol if it does not have one 498 if (!(rsym->reserved() & ReservePLT)){ 499 // Create .got section if it doesn't exist 500 if (NULL == m_pGOT) 501 createARMGOT(pLinker, pOutput); 502 // create .plt and .rel.plt if not exist 503 if (NULL == m_pPLT) 504 createARMPLTandRelPLT(pLinker, pOutput); 505 // Symbol needs PLT entry, we need to reserve a PLT entry 506 // and the corresponding GOT and dynamic relocation entry 507 // in .got and .rel.plt. (GOT entry will be reserved simultaneously 508 // when calling ARMPLT->reserveEntry()) 509 m_pPLT->reserveEntry(); 510 m_pRelPLT->reserveEntry(*m_pRelocFactory); 511 // set PLT bit 512 rsym->setReserved(rsym->reserved() | ReservePLT); 513 } 514 } 515 516 if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 517 pLDInfo, pOutput, true)) { 518 // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 519 // create .rel.dyn section if not exist 520 if (NULL == m_pRelDyn) 521 createARMRelDyn(pLinker, pOutput); 522 m_pRelDyn->reserveEntry(*m_pRelocFactory); 523 if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo, 524 pOutput)) { 525 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym); 526 addCopyReloc(*cpy_sym.resolveInfo()); 527 } 528 else { 529 checkValidReloc(pReloc, pLDInfo, pOutput); 530 // set Rel bit 531 rsym->setReserved(rsym->reserved() | ReserveRel); 532 } 533 } 534 return; 535 } 536 537 case llvm::ELF::R_ARM_GOTOFF32: 538 case llvm::ELF::R_ARM_GOTOFF12: { 539 // A GOT section is needed 540 if (NULL == m_pGOT) 541 createARMGOT(pLinker, pOutput); 542 return; 543 } 544 545 case llvm::ELF::R_ARM_BASE_PREL: 546 case llvm::ELF::R_ARM_THM_MOVW_BREL_NC: 547 case llvm::ELF::R_ARM_THM_MOVW_BREL: 548 case llvm::ELF::R_ARM_THM_MOVT_BREL: 549 // FIXME: Currently we only support these relocations against 550 // symbol _GLOBAL_OFFSET_TABLE_ 551 if (rsym != m_pGOTSymbol->resolveInfo()) { 552 fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name() 553 << "mclinker@googlegroups.com"; 554 } 555 case llvm::ELF::R_ARM_REL32: 556 case llvm::ELF::R_ARM_LDR_PC_G0: 557 case llvm::ELF::R_ARM_SBREL32: 558 case llvm::ELF::R_ARM_THM_PC8: 559 case llvm::ELF::R_ARM_MOVW_PREL_NC: 560 case llvm::ELF::R_ARM_MOVT_PREL: 561 case llvm::ELF::R_ARM_THM_MOVW_PREL_NC: 562 case llvm::ELF::R_ARM_THM_MOVT_PREL: 563 case llvm::ELF::R_ARM_THM_ALU_PREL_11_0: 564 case llvm::ELF::R_ARM_THM_PC12: 565 case llvm::ELF::R_ARM_REL32_NOI: 566 case llvm::ELF::R_ARM_ALU_PC_G0_NC: 567 case llvm::ELF::R_ARM_ALU_PC_G0: 568 case llvm::ELF::R_ARM_ALU_PC_G1_NC: 569 case llvm::ELF::R_ARM_ALU_PC_G1: 570 case llvm::ELF::R_ARM_ALU_PC_G2: 571 case llvm::ELF::R_ARM_LDR_PC_G1: 572 case llvm::ELF::R_ARM_LDR_PC_G2: 573 case llvm::ELF::R_ARM_LDRS_PC_G0: 574 case llvm::ELF::R_ARM_LDRS_PC_G1: 575 case llvm::ELF::R_ARM_LDRS_PC_G2: 576 case llvm::ELF::R_ARM_LDC_PC_G0: 577 case llvm::ELF::R_ARM_LDC_PC_G1: 578 case llvm::ELF::R_ARM_LDC_PC_G2: 579 case llvm::ELF::R_ARM_ALU_SB_G0_NC: 580 case llvm::ELF::R_ARM_ALU_SB_G0: 581 case llvm::ELF::R_ARM_ALU_SB_G1_NC: 582 case llvm::ELF::R_ARM_ALU_SB_G1: 583 case llvm::ELF::R_ARM_ALU_SB_G2: 584 case llvm::ELF::R_ARM_LDR_SB_G0: 585 case llvm::ELF::R_ARM_LDR_SB_G1: 586 case llvm::ELF::R_ARM_LDR_SB_G2: 587 case llvm::ELF::R_ARM_LDRS_SB_G0: 588 case llvm::ELF::R_ARM_LDRS_SB_G1: 589 case llvm::ELF::R_ARM_LDRS_SB_G2: 590 case llvm::ELF::R_ARM_LDC_SB_G0: 591 case llvm::ELF::R_ARM_LDC_SB_G1: 592 case llvm::ELF::R_ARM_LDC_SB_G2: 593 case llvm::ELF::R_ARM_MOVW_BREL_NC: 594 case llvm::ELF::R_ARM_MOVT_BREL: 595 case llvm::ELF::R_ARM_MOVW_BREL: { 596 // Relative addressing relocation, may needs dynamic relocation 597 if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), 598 pLDInfo, pOutput, false)) { 599 // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 600 // create .rel.dyn section if not exist 601 if (NULL == m_pRelDyn) 602 createARMRelDyn(pLinker, pOutput); 603 m_pRelDyn->reserveEntry(*m_pRelocFactory); 604 if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo, 605 pOutput)) { 606 LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym); 607 addCopyReloc(*cpy_sym.resolveInfo()); 608 } 609 else { 610 checkValidReloc(pReloc, pLDInfo, pOutput); 611 // set Rel bit 612 rsym->setReserved(rsym->reserved() | ReserveRel); 613 } 614 } 615 return; 616 } 617 618 case llvm::ELF::R_ARM_THM_CALL: 619 case llvm::ELF::R_ARM_PLT32: 620 case llvm::ELF::R_ARM_CALL: 621 case llvm::ELF::R_ARM_JUMP24: 622 case llvm::ELF::R_ARM_THM_JUMP24: 623 case llvm::ELF::R_ARM_SBREL31: 624 case llvm::ELF::R_ARM_PREL31: 625 case llvm::ELF::R_ARM_THM_JUMP19: 626 case llvm::ELF::R_ARM_THM_JUMP6: 627 case llvm::ELF::R_ARM_THM_JUMP11: 628 case llvm::ELF::R_ARM_THM_JUMP8: { 629 // These are branch relocation (except PREL31) 630 // A PLT entry is needed when building shared library 631 632 // return if we already create plt for this symbol 633 if (rsym->reserved() & ReservePLT) 634 return; 635 636 // if symbol is defined in the ouput file and it's not 637 // preemptible, no need plt 638 if (rsym->isDefine() && !rsym->isDyn() && 639 !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) { 640 return; 641 } 642 643 // Create .got section if it doesn't exist 644 if (NULL == m_pGOT) 645 createARMGOT(pLinker, pOutput); 646 647 // create .plt and .rel.plt if not exist 648 if (NULL == m_pPLT) 649 createARMPLTandRelPLT(pLinker, pOutput); 650 // Symbol needs PLT entry, we need to reserve a PLT entry 651 // and the corresponding GOT and dynamic relocation entry 652 // in .got and .rel.plt. (GOT entry will be reserved simultaneously 653 // when calling ARMPLT->reserveEntry()) 654 m_pPLT->reserveEntry(); 655 m_pRelPLT->reserveEntry(*m_pRelocFactory); 656 // set PLT bit 657 rsym->setReserved(rsym->reserved() | ReservePLT); 658 return; 659 } 660 661 // Set R_ARM_TARGET2 to R_ARM_GOT_PREL 662 // Ref: GNU gold 1.11 arm.cc, line 9892 663 // FIXME: R_ARM_TARGET2 should be set by option --target2 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() & (ReserveGOT | GOTRel)) 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() | GOTRel); 686 return; 687 } 688 // set GOT bit 689 rsym->setReserved(rsym->reserved() | ReserveGOT); 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 fatal(diag::dynamic_relocation) << (int)pReloc.type(); 700 break; 701 } 702 default: { 703 break; 704 } 705 } // end switch 706} 707 708void ARMGNULDBackend::scanRelocation(Relocation& pReloc, 709 const LDSymbol& pInputSym, 710 MCLinker& pLinker, 711 const MCLDInfo& pLDInfo, 712 const Output& pOutput, 713 const LDSection& pSection) 714{ 715 // rsym - The relocation target symbol 716 ResolveInfo* rsym = pReloc.symInfo(); 717 assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation"); 718 719 assert(NULL != pSection.getLink()); 720 if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) { 721 if (rsym->isLocal()) { 722 updateAddend(pReloc, pInputSym, pLinker.getLayout()); 723 } 724 return; 725 } 726 727 // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation 728 // entries should be created. 729 // FIXME: Below judgements concern only .so is generated as output 730 // FIXME: Below judgements concern nothing about TLS related relocation 731 732 // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section 733 // is needed 734 if (NULL == m_pGOT && NULL != m_pGOTSymbol) { 735 if (rsym == m_pGOTSymbol->resolveInfo()) { 736 createARMGOT(pLinker, pOutput); 737 } 738 } 739 740 // rsym is local 741 if (rsym->isLocal()) 742 scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput); 743 744 // rsym is external 745 else 746 scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput); 747 748} 749 750uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput, 751 const LDSection& pSection, 752 const MCLDInfo& pInfo, 753 const Layout& pLayout, 754 MemoryRegion& pRegion) const 755{ 756 assert(pRegion.size() && "Size of MemoryRegion is zero!"); 757 758 const ELFFileFormat* file_format = getOutputFormat(pOutput); 759 760 if (&pSection == m_pAttributes || 761 &pSection == m_pEXIDX || 762 &pSection == m_pEXTAB) { 763 // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab 764 // directly from the input file. 765 const llvm::MCSectionData* sect_data = pSection.getSectionData(); 766 llvm::MCSectionData::const_iterator frag_iter, frag_end = sect_data->end(); 767 uint8_t* out_offset = pRegion.start(); 768 for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) { 769 size_t size = computeFragmentSize(pLayout, *frag_iter); 770 switch(frag_iter->getKind()) { 771 case llvm::MCFragment::FT_Region: { 772 const MCRegionFragment& region_frag = 773 llvm::cast<MCRegionFragment>(*frag_iter); 774 const uint8_t* start = region_frag.getRegion().start(); 775 memcpy(out_offset, start, size); 776 break; 777 } 778 case llvm::MCFragment::FT_Align: { 779 llvm::MCAlignFragment& align_frag = 780 llvm::cast<llvm::MCAlignFragment>(*frag_iter); 781 uint64_t count = size / align_frag.getValueSize(); 782 switch (align_frag.getValueSize()) { 783 case 1u: 784 std::memset(out_offset, align_frag.getValue(), count); 785 break; 786 default: 787 llvm::report_fatal_error( 788 "unsupported value size for align fragment emission yet.\n"); 789 break; 790 } // end switch 791 break; 792 } 793 default: 794 llvm::report_fatal_error("unsupported fragment type.\n"); 795 break; 796 } // end switch 797 out_offset += size; 798 } // end for 799 return pRegion.size(); 800 } // end if 801 802 if (&pSection == &(file_format->getPLT())) { 803 assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!"); 804 uint64_t result = m_pPLT->emit(pRegion); 805 return result; 806 } 807 808 if (&pSection == &(file_format->getGOT())) { 809 assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!"); 810 uint64_t result = m_pGOT->emit(pRegion); 811 return result; 812 } 813 fatal(diag::unrecognized_output_sectoin) 814 << pSection.name() 815 << "mclinker@googlegroups.com"; 816 return 0x0; 817} 818 819/// finalizeSymbol - finalize the symbol value 820bool ARMGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput) 821{ 822 return true; 823} 824 825bool ARMGNULDBackend::readSection(Input& pInput, 826 MCLinker& pLinker, 827 LDSection& pInputSectHdr) 828{ 829 LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(), 830 pInputSectHdr.kind(), 831 pInputSectHdr.type(), 832 pInputSectHdr.flag()); 833 // FIXME: (Luba) 834 // Handle ARM attributes in the right way. 835 // In current milestone, MCLinker goes through the shortcut. 836 // It reads input's ARM attributes and copies the first ARM attributes 837 // into the output file. The correct way is merge these sections, not 838 // just copy. 839 if ((0 == out_sect.name().compare(".ARM.attributes")) && 840 (0 != out_sect.size())) 841 return true; 842 843 MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(), 844 pInputSectHdr.size()); 845 846 llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr); 847 848 llvm::MCFragment* frag = NULL; 849 if (NULL == region) { 850 // If the input section's size is zero, we got a NULL region. 851 // use a virtual fill fragment 852 frag = new llvm::MCFillFragment(0x0, 0, 0); 853 } 854 else 855 frag = new MCRegionFragment(*region); 856 857 uint64_t size = pLinker.getLayout().appendFragment(*frag, 858 sect_data, 859 pInputSectHdr.align()); 860 861 out_sect.setSize(out_sect.size() + size); 862 return true; 863} 864 865ARMGOT& ARMGNULDBackend::getGOT() 866{ 867 assert(NULL != m_pGOT && "GOT section not exist"); 868 return *m_pGOT; 869} 870 871const ARMGOT& ARMGNULDBackend::getGOT() const 872{ 873 assert(NULL != m_pGOT && "GOT section not exist"); 874 return *m_pGOT; 875} 876 877ARMPLT& ARMGNULDBackend::getPLT() 878{ 879 assert(NULL != m_pPLT && "PLT section not exist"); 880 return *m_pPLT; 881} 882 883const ARMPLT& ARMGNULDBackend::getPLT() const 884{ 885 assert(NULL != m_pPLT && "PLT section not exist"); 886 return *m_pPLT; 887} 888 889OutputRelocSection& ARMGNULDBackend::getRelDyn() 890{ 891 assert(NULL != m_pRelDyn && ".rel.dyn section not exist"); 892 return *m_pRelDyn; 893} 894 895const OutputRelocSection& ARMGNULDBackend::getRelDyn() const 896{ 897 assert(NULL != m_pRelDyn && ".rel.dyn section not exist"); 898 return *m_pRelDyn; 899} 900 901OutputRelocSection& ARMGNULDBackend::getRelPLT() 902{ 903 assert(NULL != m_pRelPLT && ".rel.plt section not exist"); 904 return *m_pRelPLT; 905} 906 907const OutputRelocSection& ARMGNULDBackend::getRelPLT() const 908{ 909 assert(NULL != m_pRelPLT && ".rel.plt section not exist"); 910 return *m_pRelPLT; 911} 912 913unsigned int 914ARMGNULDBackend::getTargetSectionOrder(const Output& pOutput, 915 const LDSection& pSectHdr, 916 const MCLDInfo& pInfo) const 917{ 918 const ELFFileFormat* file_format = getOutputFormat(pOutput); 919 920 if (&pSectHdr == &file_format->getGOT()) { 921 if (pInfo.options().hasNow()) 922 return SHO_RELRO_LAST; 923 return SHO_DATA; 924 } 925 926 if (&pSectHdr == &file_format->getPLT()) 927 return SHO_PLT; 928 929 if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) { 930 // put ARM.exidx and ARM.extab in the same order of .eh_frame 931 return SHO_EXCEPTION; 932 } 933 934 return SHO_UNDEFINED; 935} 936 937namespace mcld { 938 939//===----------------------------------------------------------------------===// 940/// createARMLDBackend - the help funtion to create corresponding ARMLDBackend 941/// 942TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget, 943 const std::string& pTriple) 944{ 945 Triple theTriple(pTriple); 946 if (theTriple.isOSDarwin()) { 947 assert(0 && "MachO linker is not supported yet"); 948 /** 949 return new ARMMachOLDBackend(createARMMachOArchiveReader, 950 createARMMachOObjectReader, 951 createARMMachOObjectWriter); 952 **/ 953 } 954 if (theTriple.isOSWindows()) { 955 assert(0 && "COFF linker is not supported yet"); 956 /** 957 return new ARMCOFFLDBackend(createARMCOFFArchiveReader, 958 createARMCOFFObjectReader, 959 createARMCOFFObjectWriter); 960 **/ 961 } 962 return new ARMGNULDBackend(); 963} 964 965} // namespace of mcld 966 967//============================= 968// Force static initialization. 969extern "C" void LLVMInitializeARMLDBackend() { 970 // Register the linker backend 971 mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend); 972 mcld::TargetRegistry::RegisterTargetLDBackend(TheThumbTarget, createARMLDBackend); 973} 974 975