1//===- MipsLDBackend.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 10#include <llvm/ADT/Triple.h> 11#include <llvm/Support/ELF.h> 12 13#include <mcld/LD/SectionMap.h> 14#include <mcld/MC/MCLDInfo.h> 15#include <mcld/MC/MCLinker.h> 16#include <mcld/Support/MemoryRegion.h> 17#include <mcld/Support/TargetRegistry.h> 18#include <mcld/Target/OutputRelocSection.h> 19 20#include "Mips.h" 21#include "MipsELFDynamic.h" 22#include "MipsLDBackend.h" 23#include "MipsRelocationFactory.h" 24 25enum { 26 // The original o32 abi. 27 E_MIPS_ABI_O32 = 0x00001000, 28 // O32 extended to work on 64 bit architectures. 29 E_MIPS_ABI_O64 = 0x00002000, 30 // EABI in 32 bit mode. 31 E_MIPS_ABI_EABI32 = 0x00003000, 32 // EABI in 64 bit mode. 33 E_MIPS_ABI_EABI64 = 0x00004000 34}; 35 36namespace mcld { 37 38MipsGNULDBackend::MipsGNULDBackend() 39 : m_pRelocFactory(NULL), 40 m_pGOT(NULL), 41 m_pRelDyn(NULL), 42 m_pDynamic(NULL), 43 m_pGOTSymbol(NULL), 44 m_pGpDispSymbol(NULL) 45{ 46} 47 48MipsGNULDBackend::~MipsGNULDBackend() 49{ 50 if (NULL != m_pRelocFactory) 51 delete m_pRelocFactory; 52 if (NULL != m_pGOT) 53 delete m_pGOT; 54 if (NULL != m_pRelDyn) 55 delete m_pRelDyn; 56 if (NULL != m_pDynamic) 57 delete m_pDynamic; 58} 59 60bool MipsGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap) 61{ 62 // Nothing to do because we do not support 63 // any MIPS specific sections now. 64 return true; 65} 66 67void MipsGNULDBackend::initTargetSections(MCLinker& pLinker) 68{ 69 // Nothing to do because we do not support 70 // any MIPS specific sections now. 71} 72 73void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker) 74{ 75 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the 76 // same name in input 77 m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>( 78 "_GLOBAL_OFFSET_TABLE_", 79 false, 80 ResolveInfo::Object, 81 ResolveInfo::Define, 82 ResolveInfo::Local, 83 0x0, // size 84 0x0, // value 85 NULL, // FragRef 86 ResolveInfo::Hidden); 87 88 m_pGpDispSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>( 89 "_gp_disp", 90 false, 91 ResolveInfo::Section, 92 ResolveInfo::Define, 93 ResolveInfo::Absolute, 94 0x0, // size 95 0x0, // value 96 NULL, // FragRef 97 ResolveInfo::Default); 98 99 if (NULL != m_pGpDispSymbol) { 100 m_pGpDispSymbol->resolveInfo()->setReserved(ReserveGpDisp); 101 } 102} 103 104bool MipsGNULDBackend::initRelocFactory(const MCLinker& pLinker) 105{ 106 if (NULL == m_pRelocFactory) { 107 m_pRelocFactory = new MipsRelocationFactory(1024, *this); 108 m_pRelocFactory->setLayout(pLinker.getLayout()); 109 } 110 return true; 111} 112 113RelocationFactory* MipsGNULDBackend::getRelocFactory() 114{ 115 assert(NULL != m_pRelocFactory); 116 return m_pRelocFactory; 117} 118 119void MipsGNULDBackend::scanRelocation(Relocation& pReloc, 120 const LDSymbol& pInputSym, 121 MCLinker& pLinker, 122 const MCLDInfo& pLDInfo, 123 const Output& pOutput) 124{ 125 // rsym - The relocation target symbol 126 ResolveInfo* rsym = pReloc.symInfo(); 127 assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation"); 128 129 // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies 130 // that a .got section is needed. 131 if (NULL == m_pGOT && NULL != m_pGOTSymbol) { 132 if (rsym == m_pGOTSymbol->resolveInfo()) { 133 createGOT(pLinker, pOutput); 134 } 135 } 136 137 if (rsym->isLocal()) 138 scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput); 139 else 140 scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput); 141} 142 143uint32_t MipsGNULDBackend::machine() const 144{ 145 return llvm::ELF::EM_MIPS; 146} 147 148uint8_t MipsGNULDBackend::OSABI() const 149{ 150 return llvm::ELF::ELFOSABI_NONE; 151} 152 153uint8_t MipsGNULDBackend::ABIVersion() const 154{ 155 return 0; 156} 157 158uint64_t MipsGNULDBackend::flags() const 159{ 160 // TODO: (simon) The correct flag's set depend on command line 161 // arguments and flags from input .o files. 162 return llvm::ELF::EF_MIPS_ARCH_32R2 | 163 llvm::ELF::EF_MIPS_NOREORDER | 164 llvm::ELF::EF_MIPS_PIC | 165 llvm::ELF::EF_MIPS_CPIC | 166 E_MIPS_ABI_O32; 167} 168 169bool MipsGNULDBackend::isLittleEndian() const 170{ 171 // Now we support little endian (mipsel) target only. 172 return true; 173} 174 175unsigned int MipsGNULDBackend::bitclass() const 176{ 177 return 32; 178} 179 180void MipsGNULDBackend::doPreLayout(const Output& pOutput, 181 const MCLDInfo& pInfo, 182 MCLinker& pLinker) 183{ 184 // when building shared object, the .got section is must. 185 if (pOutput.type() == Output::DynObj && NULL == m_pGOT) { 186 createGOT(pLinker, pOutput); 187 } 188} 189 190void MipsGNULDBackend::doPostLayout(const Output& pOutput, 191 const MCLDInfo& pInfo, 192 MCLinker& pLinker) 193{ 194 // emit program headers 195 if (pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) 196 emitProgramHdrs(pLinker.getLDInfo().output()); 197} 198 199/// dynamic - the dynamic section of the target machine. 200/// Use co-variant return type to return its own dynamic section. 201MipsELFDynamic& MipsGNULDBackend::dynamic() 202{ 203 if (NULL == m_pDynamic) 204 m_pDynamic = new MipsELFDynamic(*this); 205 206 return *m_pDynamic; 207} 208 209/// dynamic - the dynamic section of the target machine. 210/// Use co-variant return type to return its own dynamic section. 211const MipsELFDynamic& MipsGNULDBackend::dynamic() const 212{ 213 assert( NULL != m_pDynamic); 214 return *m_pDynamic; 215} 216 217uint64_t MipsGNULDBackend::emitSectionData(const Output& pOutput, 218 const LDSection& pSection, 219 const MCLDInfo& pInfo, 220 MemoryRegion& pRegion) const 221{ 222 assert(pRegion.size() && "Size of MemoryRegion is zero!"); 223 224 ELFFileFormat* file_format = getOutputFormat(pOutput); 225 226 if (&pSection == &(file_format->getGOT())) { 227 assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!"); 228 uint64_t result = m_pGOT->emit(pRegion); 229 return result; 230 } 231 232 llvm::report_fatal_error(llvm::Twine("Unable to emit section `") + 233 pSection.name() + 234 llvm::Twine("'.\n")); 235 return 0; 236} 237/// isGOTSymbol - return true if the symbol is the GOT entry. 238bool MipsGNULDBackend::isGOTSymbol(const LDSymbol& pSymbol) const 239{ 240 return std::find(m_LocalGOTSyms.begin(), 241 m_LocalGOTSyms.end(), &pSymbol) != m_LocalGOTSyms.end() || 242 std::find(m_GlobalGOTSyms.begin(), 243 m_GlobalGOTSyms.end(), &pSymbol) != m_GlobalGOTSyms.end(); 244} 245 246/// emitDynamicSymbol - emit dynamic symbol. 247void MipsGNULDBackend::emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32, 248 Output& pOutput, 249 LDSymbol& pSymbol, 250 const Layout& pLayout, 251 char* strtab, 252 size_t strtabsize, 253 size_t symtabIdx) 254{ 255 // maintain output's symbol and index map 256 bool sym_exist = false; 257 HashTableType::entry_type* entry = 0; 258 entry = m_pSymIndexMap->insert(&pSymbol, sym_exist); 259 entry->setValue(symtabIdx); 260 261 // FIXME: check the endian between host and target 262 // write out symbol 263 sym32.st_name = strtabsize; 264 sym32.st_value = pSymbol.value(); 265 sym32.st_size = getSymbolSize(pSymbol); 266 sym32.st_info = getSymbolInfo(pSymbol); 267 sym32.st_other = pSymbol.visibility(); 268 sym32.st_shndx = getSymbolShndx(pSymbol, pLayout); 269 // write out string 270 strcpy((strtab + strtabsize), pSymbol.name()); 271} 272 273/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash 274/// 275/// the size of these tables should be computed before layout 276/// layout should computes the start offset of these tables 277void MipsGNULDBackend::emitDynNamePools(Output& pOutput, 278 SymbolCategory& pSymbols, 279 const Layout& pLayout, 280 const MCLDInfo& pLDInfo) 281{ 282 assert(pOutput.hasMemArea()); 283 ELFFileFormat* file_format = getOutputFormat(pOutput); 284 285 LDSection& symtab_sect = file_format->getDynSymTab(); 286 LDSection& strtab_sect = file_format->getDynStrTab(); 287 LDSection& hash_sect = file_format->getHashTab(); 288 LDSection& dyn_sect = file_format->getDynamic(); 289 290 MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(), 291 symtab_sect.size()); 292 MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(), 293 strtab_sect.size()); 294 MemoryRegion* hash_region = pOutput.memArea()->request(hash_sect.offset(), 295 hash_sect.size()); 296 MemoryRegion* dyn_region = pOutput.memArea()->request(dyn_sect.offset(), 297 dyn_sect.size()); 298 // set up symtab_region 299 llvm::ELF::Elf32_Sym* symtab32 = NULL; 300 symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start(); 301 302 symtab32[0].st_name = 0; 303 symtab32[0].st_value = 0; 304 symtab32[0].st_size = 0; 305 symtab32[0].st_info = 0; 306 symtab32[0].st_other = 0; 307 symtab32[0].st_shndx = 0; 308 309 // set up strtab_region 310 char* strtab = (char*)strtab_region->start(); 311 strtab[0] = '\0'; 312 313 bool sym_exist = false; 314 HashTableType::entry_type* entry = 0; 315 316 // add index 0 symbol into SymIndexMap 317 entry = m_pSymIndexMap->insert(NULL, sym_exist); 318 entry->setValue(0); 319 320 size_t symtabIdx = 1; 321 size_t strtabsize = 1; 322 323 // emit of .dynsym, and .dynstr except GOT entries 324 for (SymbolCategory::iterator symbol = pSymbols.begin(), 325 sym_end = pSymbols.end(); symbol != sym_end; ++symbol) { 326 if (!isDynamicSymbol(**symbol, pOutput)) 327 continue; 328 329 if (isGOTSymbol(**symbol)) 330 continue; 331 332 emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab, 333 strtabsize, symtabIdx); 334 335 // sum up counters 336 ++symtabIdx; 337 strtabsize += (*symbol)->nameSize() + 1; 338 } 339 340 // emit global GOT 341 for (std::vector<LDSymbol*>::const_iterator symbol = m_GlobalGOTSyms.begin(), 342 symbol_end = m_GlobalGOTSyms.end(); 343 symbol != symbol_end; ++symbol) { 344 345 emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab, 346 strtabsize, symtabIdx); 347 348 // sum up counters 349 ++symtabIdx; 350 strtabsize += (*symbol)->nameSize() + 1; 351 } 352 353 // emit DT_NEED 354 // add DT_NEED strings into .dynstr 355 // Rules: 356 // 1. ignore --no-add-needed 357 // 2. force count in --no-as-needed 358 // 3. judge --as-needed 359 ELFDynamic::iterator dt_need = dynamic().needBegin(); 360 InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end(); 361 for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) { 362 if (Input::DynObj == (*input)->type()) { 363 // --add-needed 364 if ((*input)->attribute()->isAddNeeded()) { 365 // --no-as-needed 366 if (!(*input)->attribute()->isAsNeeded()) { 367 strcpy((strtab + strtabsize), (*input)->name().c_str()); 368 (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize); 369 strtabsize += (*input)->name().size() + 1; 370 ++dt_need; 371 } 372 // --as-needed 373 else if ((*input)->isNeeded()) { 374 strcpy((strtab + strtabsize), (*input)->name().c_str()); 375 (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize); 376 strtabsize += (*input)->name().size() + 1; 377 ++dt_need; 378 } 379 } 380 } 381 } // for 382 383 // emit soname 384 // initialize value of ELF .dynamic section 385 dynamic().applySoname(strtabsize); 386 dynamic().applyEntries(pLDInfo, *file_format); 387 dynamic().emit(dyn_sect, *dyn_region); 388 389 strcpy((strtab + strtabsize), pOutput.name().c_str()); 390 strtabsize += pOutput.name().size() + 1; 391 392 // emit hash table 393 // FIXME: this verion only emit SVR4 hash section. 394 // Please add GNU new hash section 395 396 // both 32 and 64 bits hash table use 32-bit entry 397 // set up hash_region 398 uint32_t* word_array = (uint32_t*)hash_region->start(); 399 uint32_t& nbucket = word_array[0]; 400 uint32_t& nchain = word_array[1]; 401 402 nbucket = getHashBucketCount(symtabIdx, false); 403 nchain = symtabIdx; 404 405 uint32_t* bucket = (word_array + 2); 406 uint32_t* chain = (bucket + nbucket); 407 408 // initialize bucket 409 bzero((void*)bucket, nbucket); 410 411 StringHash<ELF> hash_func; 412 413 for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) { 414 llvm::StringRef name(strtab + symtab32[sym_idx].st_name); 415 size_t bucket_pos = hash_func(name) % nbucket; 416 chain[sym_idx] = bucket[bucket_pos]; 417 bucket[bucket_pos] = sym_idx; 418 } 419 420} 421 422MipsGOT& MipsGNULDBackend::getGOT() 423{ 424 assert(NULL != m_pGOT); 425 return *m_pGOT; 426} 427 428const MipsGOT& MipsGNULDBackend::getGOT() const 429{ 430 assert(NULL != m_pGOT); 431 return *m_pGOT; 432} 433 434OutputRelocSection& MipsGNULDBackend::getRelDyn() 435{ 436 assert(NULL != m_pRelDyn); 437 return *m_pRelDyn; 438} 439 440const OutputRelocSection& MipsGNULDBackend::getRelDyn() const 441{ 442 assert(NULL != m_pRelDyn); 443 return *m_pRelDyn; 444} 445 446unsigned int 447MipsGNULDBackend::getTargetSectionOrder(const Output& pOutput, 448 const LDSection& pSectHdr) const 449{ 450 ELFFileFormat* file_format = getOutputFormat(pOutput); 451 452 if (&pSectHdr == &file_format->getGOT()) 453 return SHO_DATA; 454 455 return SHO_UNDEFINED; 456} 457 458/// finalizeSymbol - finalize the symbol value 459/// If the symbol's reserved field is not zero, MCLinker will call back this 460/// function to ask the final value of the symbol 461bool MipsGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const 462{ 463 if (&pSymbol == m_pGpDispSymbol) { 464 m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0); 465 return true; 466 } 467 return false; 468} 469 470/// allocateCommonSymbols - allocate common symbols in the corresponding 471/// sections. 472/// @refer Google gold linker: common.cc: 214 473/// FIXME: Mips needs to allocate small common symbol 474bool 475MipsGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const 476{ 477 // SymbolCategory contains all symbols that must emit to the output files. 478 // We are not like Google gold linker, we don't remember symbols before symbol 479 // resolution. All symbols in SymbolCategory are already resolved. Therefore, we 480 // don't need to care about some symbols may be changed its category due to symbol 481 // resolution. 482 SymbolCategory& symbol_list = pLinker.getOutputSymbols(); 483 484 if (symbol_list.emptyCommons() && symbol_list.emptyLocals()) 485 return true; 486 487 // addralign := max value of all common symbols 488 uint64_t addralign = 0x0; 489 490 // Due to the visibility, some common symbols may be forcefully local. 491 SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd(); 492 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) { 493 if (ResolveInfo::Common == (*com_sym)->desc()) { 494 if ((*com_sym)->value() > addralign) 495 addralign = (*com_sym)->value(); 496 } 497 } 498 499 // global common symbols. 500 com_end = symbol_list.commonEnd(); 501 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) { 502 if ((*com_sym)->value() > addralign) 503 addralign = (*com_sym)->value(); 504 } 505 506 // FIXME: If the order of common symbols is defined, then sort common symbols 507 // com_sym = symbol_list.commonBegin(); 508 // std::sort(com_sym, com_end, some kind of order); 509 510 // get or create corresponding BSS LDSection 511 LDSection* bss_sect_hdr = NULL; 512 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) { 513 bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr( 514 ".tbss", 515 LDFileFormat::BSS, 516 llvm::ELF::SHT_NOBITS, 517 llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC); 518 } 519 else { 520 bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss", 521 LDFileFormat::BSS, 522 llvm::ELF::SHT_NOBITS, 523 llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC); 524 } 525 526 // get or create corresponding BSS MCSectionData 527 assert(NULL != bss_sect_hdr); 528 llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr); 529 530 // allocate all common symbols 531 uint64_t offset = bss_sect_hdr->size(); 532 533 // allocate all local common symbols 534 com_end = symbol_list.localEnd(); 535 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) { 536 if (ResolveInfo::Common == (*com_sym)->desc()) { 537 alignAddress(offset, (*com_sym)->value()); 538 // We have to reset the description of the symbol here. When doing 539 // incremental linking, the output relocatable object may have common 540 // symbols. Therefore, we can not treat common symbols as normal symbols 541 // when emitting the regular name pools. We must change the symbols' 542 // description here. 543 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define); 544 llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section); 545 (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0)); 546 offset += (*com_sym)->size(); 547 } 548 } 549 550 // allocate all global common symbols 551 com_end = symbol_list.commonEnd(); 552 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) { 553 alignAddress(offset, (*com_sym)->value()); 554 555 // We have to reset the description of the symbol here. When doing 556 // incremental linking, the output relocatable object may have common 557 // symbols. Therefore, we can not treat common symbols as normal symbols 558 // when emitting the regular name pools. We must change the symbols' 559 // description here. 560 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define); 561 llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section); 562 (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0)); 563 offset += (*com_sym)->size(); 564 } 565 566 bss_sect_hdr->setSize(offset); 567 symbol_list.changeCommonsToGlobal(); 568 return true; 569} 570 571void MipsGNULDBackend::updateAddend(Relocation& pReloc, 572 const LDSymbol& pInputSym, 573 const Layout& pLayout) const 574{ 575 // Update value keep in addend if we meet a section symbol 576 if(pReloc.symInfo()->type() == ResolveInfo::Section) { 577 pReloc.setAddend(pLayout.getOutputOffset( 578 *pInputSym.fragRef()) + pReloc.addend()); 579 } 580} 581 582void MipsGNULDBackend::scanLocalReloc(Relocation& pReloc, 583 const LDSymbol& pInputSym, 584 MCLinker& pLinker, 585 const MCLDInfo& pLDInfo, 586 const Output& pOutput) 587{ 588 ResolveInfo* rsym = pReloc.symInfo(); 589 590 updateAddend(pReloc, pInputSym, pLinker.getLayout()); 591 592 switch (pReloc.type()){ 593 case llvm::ELF::R_MIPS_NONE: 594 case llvm::ELF::R_MIPS_16: 595 break; 596 case llvm::ELF::R_MIPS_32: 597 if (Output::DynObj == pOutput.type()) { 598 // TODO: (simon) The gold linker does not create an entry in .rel.dyn 599 // section if the symbol section flags contains SHF_EXECINSTR. 600 // 1. Find the reason of this condition. 601 // 2. Check this condition here. 602 if (NULL == m_pRelDyn) 603 createRelDyn(pLinker, pOutput); 604 605 m_pRelDyn->reserveEntry(*m_pRelocFactory); 606 rsym->setReserved(rsym->reserved() | ReserveRel); 607 } 608 break; 609 case llvm::ELF::R_MIPS_REL32: 610 case llvm::ELF::R_MIPS_26: 611 case llvm::ELF::R_MIPS_HI16: 612 case llvm::ELF::R_MIPS_LO16: 613 case llvm::ELF::R_MIPS_PC16: 614 case llvm::ELF::R_MIPS_SHIFT5: 615 case llvm::ELF::R_MIPS_SHIFT6: 616 case llvm::ELF::R_MIPS_64: 617 case llvm::ELF::R_MIPS_GOT_PAGE: 618 case llvm::ELF::R_MIPS_GOT_OFST: 619 case llvm::ELF::R_MIPS_SUB: 620 case llvm::ELF::R_MIPS_INSERT_A: 621 case llvm::ELF::R_MIPS_INSERT_B: 622 case llvm::ELF::R_MIPS_DELETE: 623 case llvm::ELF::R_MIPS_HIGHER: 624 case llvm::ELF::R_MIPS_HIGHEST: 625 case llvm::ELF::R_MIPS_SCN_DISP: 626 case llvm::ELF::R_MIPS_REL16: 627 case llvm::ELF::R_MIPS_ADD_IMMEDIATE: 628 case llvm::ELF::R_MIPS_PJUMP: 629 case llvm::ELF::R_MIPS_RELGOT: 630 case llvm::ELF::R_MIPS_JALR: 631 case llvm::ELF::R_MIPS_GLOB_DAT: 632 case llvm::ELF::R_MIPS_COPY: 633 case llvm::ELF::R_MIPS_JUMP_SLOT: 634 break; 635 case llvm::ELF::R_MIPS_GOT16: 636 case llvm::ELF::R_MIPS_CALL16: 637 if (NULL == m_pGOT) 638 createGOT(pLinker, pOutput); 639 640 if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) { 641 m_pGOT->reserveLocalEntry(); 642 rsym->setReserved(rsym->reserved() | ReserveGot); 643 m_LocalGOTSyms.push_back(rsym->outSymbol()); 644 } 645 break; 646 case llvm::ELF::R_MIPS_GPREL32: 647 case llvm::ELF::R_MIPS_GPREL16: 648 case llvm::ELF::R_MIPS_LITERAL: 649 break; 650 case llvm::ELF::R_MIPS_GOT_DISP: 651 case llvm::ELF::R_MIPS_GOT_HI16: 652 case llvm::ELF::R_MIPS_CALL_HI16: 653 case llvm::ELF::R_MIPS_GOT_LO16: 654 case llvm::ELF::R_MIPS_CALL_LO16: 655 break; 656 case llvm::ELF::R_MIPS_TLS_DTPMOD32: 657 case llvm::ELF::R_MIPS_TLS_DTPREL32: 658 case llvm::ELF::R_MIPS_TLS_DTPMOD64: 659 case llvm::ELF::R_MIPS_TLS_DTPREL64: 660 case llvm::ELF::R_MIPS_TLS_GD: 661 case llvm::ELF::R_MIPS_TLS_LDM: 662 case llvm::ELF::R_MIPS_TLS_DTPREL_HI16: 663 case llvm::ELF::R_MIPS_TLS_DTPREL_LO16: 664 case llvm::ELF::R_MIPS_TLS_GOTTPREL: 665 case llvm::ELF::R_MIPS_TLS_TPREL32: 666 case llvm::ELF::R_MIPS_TLS_TPREL64: 667 case llvm::ELF::R_MIPS_TLS_TPREL_HI16: 668 case llvm::ELF::R_MIPS_TLS_TPREL_LO16: 669 break; 670 default: 671 llvm::report_fatal_error(llvm::Twine("Unknown relocation ") + 672 llvm::Twine(pReloc.type()) + 673 llvm::Twine("for the local symbol `") + 674 pReloc.symInfo()->name() + 675 llvm::Twine("'.")); 676 } 677} 678 679void MipsGNULDBackend::scanGlobalReloc(Relocation& pReloc, 680 const LDSymbol& pInputSym, 681 MCLinker& pLinker, 682 const MCLDInfo& pLDInfo, 683 const Output& pOutput) 684{ 685 ResolveInfo* rsym = pReloc.symInfo(); 686 687 switch (pReloc.type()){ 688 case llvm::ELF::R_MIPS_NONE: 689 case llvm::ELF::R_MIPS_INSERT_A: 690 case llvm::ELF::R_MIPS_INSERT_B: 691 case llvm::ELF::R_MIPS_DELETE: 692 case llvm::ELF::R_MIPS_TLS_DTPMOD64: 693 case llvm::ELF::R_MIPS_TLS_DTPREL64: 694 case llvm::ELF::R_MIPS_REL16: 695 case llvm::ELF::R_MIPS_ADD_IMMEDIATE: 696 case llvm::ELF::R_MIPS_PJUMP: 697 case llvm::ELF::R_MIPS_RELGOT: 698 case llvm::ELF::R_MIPS_TLS_TPREL64: 699 break; 700 case llvm::ELF::R_MIPS_32: 701 case llvm::ELF::R_MIPS_64: 702 case llvm::ELF::R_MIPS_HI16: 703 case llvm::ELF::R_MIPS_LO16: 704 if (isSymbolNeedsDynRel(*rsym, pOutput)) { 705 if (NULL == m_pRelDyn) 706 createRelDyn(pLinker, pOutput); 707 708 m_pRelDyn->reserveEntry(*m_pRelocFactory); 709 rsym->setReserved(rsym->reserved() | ReserveRel); 710 } 711 break; 712 case llvm::ELF::R_MIPS_GOT16: 713 case llvm::ELF::R_MIPS_CALL16: 714 case llvm::ELF::R_MIPS_GOT_DISP: 715 case llvm::ELF::R_MIPS_GOT_HI16: 716 case llvm::ELF::R_MIPS_CALL_HI16: 717 case llvm::ELF::R_MIPS_GOT_LO16: 718 case llvm::ELF::R_MIPS_CALL_LO16: 719 case llvm::ELF::R_MIPS_GOT_PAGE: 720 case llvm::ELF::R_MIPS_GOT_OFST: 721 if (NULL == m_pGOT) 722 createGOT(pLinker, pOutput); 723 724 if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) { 725 m_pGOT->reserveGlobalEntry(); 726 rsym->setReserved(rsym->reserved() | ReserveGot); 727 m_GlobalGOTSyms.push_back(rsym->outSymbol()); 728 } 729 break; 730 case llvm::ELF::R_MIPS_LITERAL: 731 case llvm::ELF::R_MIPS_GPREL32: 732 llvm::report_fatal_error(llvm::Twine("Relocation ") + 733 llvm::Twine(pReloc.type()) + 734 llvm::Twine(" is not defined for the " 735 "global symbol `") + 736 pReloc.symInfo()->name() + 737 llvm::Twine("'.")); 738 break; 739 case llvm::ELF::R_MIPS_GPREL16: 740 break; 741 case llvm::ELF::R_MIPS_26: 742 case llvm::ELF::R_MIPS_PC16: 743 break; 744 case llvm::ELF::R_MIPS_16: 745 case llvm::ELF::R_MIPS_SHIFT5: 746 case llvm::ELF::R_MIPS_SHIFT6: 747 case llvm::ELF::R_MIPS_SUB: 748 case llvm::ELF::R_MIPS_HIGHER: 749 case llvm::ELF::R_MIPS_HIGHEST: 750 case llvm::ELF::R_MIPS_SCN_DISP: 751 break; 752 case llvm::ELF::R_MIPS_TLS_DTPREL32: 753 case llvm::ELF::R_MIPS_TLS_GD: 754 case llvm::ELF::R_MIPS_TLS_LDM: 755 case llvm::ELF::R_MIPS_TLS_DTPREL_HI16: 756 case llvm::ELF::R_MIPS_TLS_DTPREL_LO16: 757 case llvm::ELF::R_MIPS_TLS_GOTTPREL: 758 case llvm::ELF::R_MIPS_TLS_TPREL32: 759 case llvm::ELF::R_MIPS_TLS_TPREL_HI16: 760 case llvm::ELF::R_MIPS_TLS_TPREL_LO16: 761 break; 762 case llvm::ELF::R_MIPS_REL32: 763 break; 764 case llvm::ELF::R_MIPS_JALR: 765 break; 766 case llvm::ELF::R_MIPS_COPY: 767 case llvm::ELF::R_MIPS_GLOB_DAT: 768 case llvm::ELF::R_MIPS_JUMP_SLOT: 769 llvm::report_fatal_error(llvm::Twine("Relocation ") + 770 llvm::Twine(pReloc.type()) + 771 llvm::Twine("for the global symbol `") + 772 pReloc.symInfo()->name() + 773 llvm::Twine("' should only be seen " 774 "by the dynamic linker")); 775 break; 776 default: 777 llvm::report_fatal_error(llvm::Twine("Unknown relocation ") + 778 llvm::Twine(pReloc.type()) + 779 llvm::Twine("for the global symbol `") + 780 pReloc.symInfo()->name() + 781 llvm::Twine("'.")); 782 } 783} 784 785bool MipsGNULDBackend::isSymbolNeedsPLT(ResolveInfo& pSym, 786 const Output& pOutput) const 787{ 788 return (Output::DynObj == pOutput.type() && 789 ResolveInfo::Function == pSym.type() && 790 (pSym.isDyn() || pSym.isUndef())); 791} 792 793bool MipsGNULDBackend::isSymbolNeedsDynRel(ResolveInfo& pSym, 794 const Output& pOutput) const 795{ 796 if(pSym.isUndef() && Output::Exec == pOutput.type()) 797 return false; 798 if(pSym.isAbsolute()) 799 return false; 800 if(Output::DynObj == pOutput.type()) 801 return true; 802 if(pSym.isDyn() || pSym.isUndef()) 803 return true; 804 805 return false; 806} 807 808void MipsGNULDBackend::createGOT(MCLinker& pLinker, const Output& pOutput) 809{ 810 ELFFileFormat* file_format = getOutputFormat(pOutput); 811 812 LDSection& got = file_format->getGOT(); 813 m_pGOT = new MipsGOT(got, pLinker.getOrCreateSectData(got)); 814 815 // define symbol _GLOBAL_OFFSET_TABLE_ when .got create 816 if( m_pGOTSymbol != NULL ) { 817 pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>( 818 "_GLOBAL_OFFSET_TABLE_", 819 false, 820 ResolveInfo::Object, 821 ResolveInfo::Define, 822 ResolveInfo::Local, 823 0x0, // size 824 0x0, // value 825 pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0), 826 ResolveInfo::Hidden); 827 } 828 else { 829 m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>( 830 "_GLOBAL_OFFSET_TABLE_", 831 false, 832 ResolveInfo::Object, 833 ResolveInfo::Define, 834 ResolveInfo::Local, 835 0x0, // size 836 0x0, // value 837 pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0), 838 ResolveInfo::Hidden); 839 } 840} 841 842void MipsGNULDBackend::createRelDyn(MCLinker& pLinker, const Output& pOutput) 843{ 844 ELFFileFormat* file_format = getOutputFormat(pOutput); 845 846 // get .rel.dyn LDSection and create MCSectionData 847 LDSection& reldyn = file_format->getRelDyn(); 848 // create MCSectionData and ARMRelDynSection 849 m_pRelDyn = new OutputRelocSection(reldyn, 850 pLinker.getOrCreateSectData(reldyn), 851 8); 852} 853 854ELFFileFormat* MipsGNULDBackend::getOutputFormat(const Output& pOutput) const 855{ 856 switch (pOutput.type()) { 857 case Output::DynObj: 858 return getDynObjFileFormat(); 859 case Output::Exec: 860 return getExecFileFormat(); 861 case Output::Object: 862 return NULL; 863 default: 864 llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") + 865 llvm::Twine(pOutput.type())); 866 return NULL; 867 } 868} 869 870//===----------------------------------------------------------------------===// 871/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend 872/// 873static TargetLDBackend* createMipsLDBackend(const llvm::Target& pTarget, 874 const std::string& pTriple) 875{ 876 llvm::Triple theTriple(pTriple); 877 if (theTriple.isOSDarwin()) { 878 assert(0 && "MachO linker is not supported yet"); 879 } 880 if (theTriple.isOSWindows()) { 881 assert(0 && "COFF linker is not supported yet"); 882 } 883 return new MipsGNULDBackend(); 884} 885 886} // namespace of mcld 887 888//============================= 889// Force static initialization. 890extern "C" void LLVMInitializeMipsLDBackend() { 891 // Register the linker backend 892 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget, 893 mcld::createMipsLDBackend); 894} 895