MipsLDBackend.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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#include "Mips.h" 10#include "MipsGNUInfo.h" 11#include "MipsELFDynamic.h" 12#include "MipsLA25Stub.h" 13#include "MipsLDBackend.h" 14#include "MipsRelocator.h" 15 16#include "mcld/IRBuilder.h" 17#include "mcld/LinkerConfig.h" 18#include "mcld/Module.h" 19#include "mcld/Fragment/FillFragment.h" 20#include "mcld/LD/BranchIslandFactory.h" 21#include "mcld/LD/LDContext.h" 22#include "mcld/LD/StubFactory.h" 23#include "mcld/LD/ELFFileFormat.h" 24#include "mcld/MC/Attribute.h" 25#include "mcld/Object/ObjectBuilder.h" 26#include "mcld/Support/MemoryRegion.h" 27#include "mcld/Support/MemoryArea.h" 28#include "mcld/Support/MsgHandling.h" 29#include "mcld/Support/TargetRegistry.h" 30#include "mcld/Target/OutputRelocSection.h" 31 32#include <llvm/ADT/Triple.h> 33#include <llvm/Support/Casting.h> 34#include <llvm/Support/ELF.h> 35#include <llvm/Support/Host.h> 36 37namespace mcld { 38 39//===----------------------------------------------------------------------===// 40// MipsGNULDBackend 41//===----------------------------------------------------------------------===// 42MipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig, 43 MipsGNUInfo* pInfo) 44 : GNULDBackend(pConfig, pInfo), 45 m_pRelocator(NULL), 46 m_pGOT(NULL), 47 m_pPLT(NULL), 48 m_pGOTPLT(NULL), 49 m_pInfo(*pInfo), 50 m_pRelPlt(NULL), 51 m_pRelDyn(NULL), 52 m_pDynamic(NULL), 53 m_pGOTSymbol(NULL), 54 m_pPLTSymbol(NULL), 55 m_pGpDispSymbol(NULL) { 56} 57 58MipsGNULDBackend::~MipsGNULDBackend() { 59 delete m_pRelocator; 60 delete m_pPLT; 61 delete m_pRelPlt; 62 delete m_pRelDyn; 63 delete m_pDynamic; 64} 65 66bool MipsGNULDBackend::needsLA25Stub(Relocation::Type pType, 67 const mcld::ResolveInfo* pSym) { 68 if (config().isCodeIndep()) 69 return false; 70 71 if (llvm::ELF::R_MIPS_26 != pType) 72 return false; 73 74 if (pSym->isLocal()) 75 return false; 76 77 return true; 78} 79 80void MipsGNULDBackend::addNonPICBranchSym(ResolveInfo* rsym) { 81 m_HasNonPICBranchSyms.insert(rsym); 82} 83 84bool MipsGNULDBackend::hasNonPICBranch(const ResolveInfo* rsym) const { 85 return m_HasNonPICBranchSyms.count(rsym); 86} 87 88void MipsGNULDBackend::initTargetSections(Module& pModule, 89 ObjectBuilder& pBuilder) { 90 if (LinkerConfig::Object == config().codeGenType()) 91 return; 92 93 ELFFileFormat* file_format = getOutputFormat(); 94 95 // initialize .rel.plt 96 LDSection& relplt = file_format->getRelPlt(); 97 m_pRelPlt = new OutputRelocSection(pModule, relplt); 98 99 // initialize .rel.dyn 100 LDSection& reldyn = file_format->getRelDyn(); 101 m_pRelDyn = new OutputRelocSection(pModule, reldyn); 102} 103 104void MipsGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) { 105 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the 106 // same name in input 107 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 108 "_GLOBAL_OFFSET_TABLE_", 109 ResolveInfo::Object, 110 ResolveInfo::Define, 111 ResolveInfo::Local, 112 0x0, // size 113 0x0, // value 114 FragmentRef::Null(), // FragRef 115 ResolveInfo::Hidden); 116 117 // Define the symbol _PROCEDURE_LINKAGE_TABLE_ if there is a symbol with the 118 // same name in input 119 m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 120 "_PROCEDURE_LINKAGE_TABLE_", 121 ResolveInfo::Object, 122 ResolveInfo::Define, 123 ResolveInfo::Local, 124 0x0, // size 125 0x0, // value 126 FragmentRef::Null(), // FragRef 127 ResolveInfo::Hidden); 128 129 m_pGpDispSymbol = 130 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 131 "_gp_disp", 132 ResolveInfo::Section, 133 ResolveInfo::Define, 134 ResolveInfo::Absolute, 135 0x0, // size 136 0x0, // value 137 FragmentRef::Null(), // FragRef 138 ResolveInfo::Default); 139 140 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>( 141 "_gp", 142 ResolveInfo::NoType, 143 ResolveInfo::Define, 144 ResolveInfo::Absolute, 145 0x0, // size 146 0x0, // value 147 FragmentRef::Null(), // FragRef 148 ResolveInfo::Default); 149} 150 151const Relocator* MipsGNULDBackend::getRelocator() const { 152 assert(m_pRelocator != NULL); 153 return m_pRelocator; 154} 155 156Relocator* MipsGNULDBackend::getRelocator() { 157 assert(m_pRelocator != NULL); 158 return m_pRelocator; 159} 160 161void MipsGNULDBackend::doPreLayout(IRBuilder& pBuilder) { 162 // initialize .dynamic data 163 if (!config().isCodeStatic() && m_pDynamic == NULL) 164 m_pDynamic = new MipsELFDynamic(*this, config()); 165 166 // set .got size 167 // when building shared object, the .got section is must. 168 if (LinkerConfig::Object != config().codeGenType()) { 169 if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() || 170 m_pGOTSymbol != NULL) { 171 m_pGOT->finalizeScanning(*m_pRelDyn); 172 m_pGOT->finalizeSectionSize(); 173 174 defineGOTSymbol(pBuilder); 175 } 176 177 if (m_pGOTPLT->hasGOT1()) { 178 m_pGOTPLT->finalizeSectionSize(); 179 180 defineGOTPLTSymbol(pBuilder); 181 } 182 183 if (m_pPLT->hasPLT1()) 184 m_pPLT->finalizeSectionSize(); 185 186 ELFFileFormat* file_format = getOutputFormat(); 187 188 // set .rel.plt size 189 if (!m_pRelPlt->empty()) { 190 assert( 191 !config().isCodeStatic() && 192 "static linkage should not result in a dynamic relocation section"); 193 file_format->getRelPlt().setSize(m_pRelPlt->numOfRelocs() * 194 getRelEntrySize()); 195 } 196 197 // set .rel.dyn size 198 if (!m_pRelDyn->empty()) { 199 assert( 200 !config().isCodeStatic() && 201 "static linkage should not result in a dynamic relocation section"); 202 file_format->getRelDyn().setSize(m_pRelDyn->numOfRelocs() * 203 getRelEntrySize()); 204 } 205 } 206} 207 208void MipsGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) { 209 const ELFFileFormat* format = getOutputFormat(); 210 211 if (format->hasGOTPLT()) { 212 assert(m_pGOTPLT != NULL && "doPostLayout failed, m_pGOTPLT is NULL!"); 213 m_pGOTPLT->applyAllGOTPLT(m_pPLT->addr()); 214 } 215 216 if (format->hasPLT()) { 217 assert(m_pPLT != NULL && "doPostLayout failed, m_pPLT is NULL!"); 218 m_pPLT->applyAllPLT(*m_pGOTPLT); 219 } 220 221 m_pInfo.setABIVersion(m_pPLT && m_pPLT->hasPLT1() ? 1 : 0); 222 223 // FIXME: (simon) We need to iterate all input sections 224 // check that flags are consistent and merge them properly. 225 uint64_t picFlags = llvm::ELF::EF_MIPS_CPIC; 226 if (config().targets().triple().isArch64Bit()) { 227 picFlags |= llvm::ELF::EF_MIPS_PIC; 228 } else { 229 if (LinkerConfig::DynObj == config().codeGenType()) 230 picFlags |= llvm::ELF::EF_MIPS_PIC; 231 } 232 233 m_pInfo.setPICFlags(picFlags); 234} 235 236/// dynamic - the dynamic section of the target machine. 237/// Use co-variant return type to return its own dynamic section. 238MipsELFDynamic& MipsGNULDBackend::dynamic() { 239 assert(m_pDynamic != NULL); 240 return *m_pDynamic; 241} 242 243/// dynamic - the dynamic section of the target machine. 244/// Use co-variant return type to return its own dynamic section. 245const MipsELFDynamic& MipsGNULDBackend::dynamic() const { 246 assert(m_pDynamic != NULL); 247 return *m_pDynamic; 248} 249 250uint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection, 251 MemoryRegion& pRegion) const { 252 assert(pRegion.size() && "Size of MemoryRegion is zero!"); 253 254 const ELFFileFormat* file_format = getOutputFormat(); 255 256 if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) { 257 return m_pGOT->emit(pRegion); 258 } 259 260 if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) { 261 return m_pPLT->emit(pRegion); 262 } 263 264 if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) { 265 return m_pGOTPLT->emit(pRegion); 266 } 267 268 fatal(diag::unrecognized_output_sectoin) << pSection.name() 269 << "mclinker@googlegroups.com"; 270 return 0; 271} 272 273bool MipsGNULDBackend::hasEntryInStrTab(const LDSymbol& pSym) const { 274 return ResolveInfo::Section != pSym.type() || m_pGpDispSymbol == &pSym; 275} 276 277namespace { 278struct DynsymGOTCompare { 279 const MipsGOT& m_pGOT; 280 281 explicit DynsymGOTCompare(const MipsGOT& pGOT) : m_pGOT(pGOT) {} 282 283 bool operator()(const LDSymbol* X, const LDSymbol* Y) const { 284 return m_pGOT.dynSymOrderCompare(X, Y); 285 } 286}; 287} // anonymous namespace 288 289void MipsGNULDBackend::orderSymbolTable(Module& pModule) { 290 if (GeneralOptions::GNU == config().options().getHashStyle() || 291 GeneralOptions::Both == config().options().getHashStyle()) { 292 // The MIPS ABI and .gnu.hash require .dynsym to be sorted 293 // in different ways. The MIPS ABI requires a mapping between 294 // the GOT and the symbol table. At the same time .gnu.hash 295 // needs symbols to be grouped by hash code. 296 llvm::errs() << ".gnu.hash is incompatible with the MIPS ABI\n"; 297 } 298 299 Module::SymbolTable& symbols = pModule.getSymbolTable(); 300 301 std::stable_sort( 302 symbols.dynamicBegin(), symbols.dynamicEnd(), DynsymGOTCompare(*m_pGOT)); 303} 304 305} // namespace mcld 306 307namespace llvm { 308namespace ELF { 309// SHT_MIPS_OPTIONS section's block descriptor. 310struct Elf_Options { 311 unsigned char kind; // Determines interpretation of variable 312 // part of descriptor. See ODK_xxx enumeration. 313 unsigned char size; // Byte size of descriptor, including this header. 314 Elf64_Half section; // Section header index of section affected, 315 // or 0 for global options. 316 Elf64_Word info; // Kind-specific information. 317}; 318 319// Type of SHT_MIPS_OPTIONS section's block. 320enum { 321 ODK_NULL = 0, // Undefined. 322 ODK_REGINFO = 1, // Register usage and GP value. 323 ODK_EXCEPTIONS = 2, // Exception processing information. 324 ODK_PAD = 3, // Section padding information. 325 ODK_HWPATCH = 4, // Hardware workarounds performed. 326 ODK_FILL = 5, // Fill value used by the linker. 327 ODK_TAGS = 6, // Reserved space for desktop tools. 328 ODK_HWAND = 7, // Hardware workarounds, AND bits when merging. 329 ODK_HWOR = 8, // Hardware workarounds, OR bits when merging. 330 ODK_GP_GROUP = 9, // GP group to use for text/data sections. 331 ODK_IDENT = 10 // ID information. 332}; 333 334// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 32 bit ABI. 335struct Elf32_RegInfo { 336 Elf32_Word ri_gprmask; // Mask of general purpose registers used. 337 Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used. 338 Elf32_Addr ri_gp_value; // GP register value for this object file. 339}; 340 341// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 64 bit ABI. 342struct Elf64_RegInfo { 343 Elf32_Word ri_gprmask; // Mask of general purpose registers used. 344 Elf32_Word ri_pad; // Padding. 345 Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used. 346 Elf64_Addr ri_gp_value; // GP register value for this object file. 347}; 348 349} // namespace ELF 350} // namespace llvm 351 352namespace mcld { 353 354bool MipsGNULDBackend::readSection(Input& pInput, SectionData& pSD) { 355 llvm::StringRef name(pSD.getSection().name()); 356 357 if (name.startswith(".sdata")) { 358 uint64_t offset = pInput.fileOffset() + pSD.getSection().offset(); 359 uint64_t size = pSD.getSection().size(); 360 361 Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size); 362 ObjectBuilder::AppendFragment(*frag, pSD); 363 return true; 364 } 365 366 if (pSD.getSection().type() == llvm::ELF::SHT_MIPS_OPTIONS) { 367 uint32_t offset = pInput.fileOffset() + pSD.getSection().offset(); 368 uint32_t size = pSD.getSection().size(); 369 370 llvm::StringRef region = pInput.memArea()->request(offset, size); 371 if (region.size() > 0) { 372 const llvm::ELF::Elf_Options* optb = 373 reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin()); 374 const llvm::ELF::Elf_Options* opte = 375 reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin() + 376 size); 377 378 for (const llvm::ELF::Elf_Options* opt = optb; opt < opte; 379 opt += opt->size) { 380 switch (opt->kind) { 381 default: 382 // Nothing to do. 383 break; 384 case llvm::ELF::ODK_REGINFO: 385 if (config().targets().triple().isArch32Bit()) { 386 const llvm::ELF::Elf32_RegInfo* reg = 387 reinterpret_cast<const llvm::ELF::Elf32_RegInfo*>(opt + 1); 388 m_GP0Map[&pInput] = reg->ri_gp_value; 389 } else { 390 const llvm::ELF::Elf64_RegInfo* reg = 391 reinterpret_cast<const llvm::ELF::Elf64_RegInfo*>(opt + 1); 392 m_GP0Map[&pInput] = reg->ri_gp_value; 393 } 394 break; 395 } 396 } 397 } 398 399 return true; 400 } 401 402 return GNULDBackend::readSection(pInput, pSD); 403} 404 405MipsGOT& MipsGNULDBackend::getGOT() { 406 assert(m_pGOT != NULL); 407 return *m_pGOT; 408} 409 410const MipsGOT& MipsGNULDBackend::getGOT() const { 411 assert(m_pGOT != NULL); 412 return *m_pGOT; 413} 414 415MipsPLT& MipsGNULDBackend::getPLT() { 416 assert(m_pPLT != NULL); 417 return *m_pPLT; 418} 419 420const MipsPLT& MipsGNULDBackend::getPLT() const { 421 assert(m_pPLT != NULL); 422 return *m_pPLT; 423} 424 425MipsGOTPLT& MipsGNULDBackend::getGOTPLT() { 426 assert(m_pGOTPLT != NULL); 427 return *m_pGOTPLT; 428} 429 430const MipsGOTPLT& MipsGNULDBackend::getGOTPLT() const { 431 assert(m_pGOTPLT != NULL); 432 return *m_pGOTPLT; 433} 434 435OutputRelocSection& MipsGNULDBackend::getRelPLT() { 436 assert(m_pRelPlt != NULL); 437 return *m_pRelPlt; 438} 439 440const OutputRelocSection& MipsGNULDBackend::getRelPLT() const { 441 assert(m_pRelPlt != NULL); 442 return *m_pRelPlt; 443} 444 445OutputRelocSection& MipsGNULDBackend::getRelDyn() { 446 assert(m_pRelDyn != NULL); 447 return *m_pRelDyn; 448} 449 450const OutputRelocSection& MipsGNULDBackend::getRelDyn() const { 451 assert(m_pRelDyn != NULL); 452 return *m_pRelDyn; 453} 454 455unsigned int MipsGNULDBackend::getTargetSectionOrder( 456 const LDSection& pSectHdr) const { 457 const ELFFileFormat* file_format = getOutputFormat(); 458 459 if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) 460 return SHO_DATA; 461 462 if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT())) 463 return SHO_DATA; 464 465 if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT())) 466 return SHO_PLT; 467 468 return SHO_UNDEFINED; 469} 470 471/// finalizeSymbol - finalize the symbol value 472bool MipsGNULDBackend::finalizeTargetSymbols() { 473 if (m_pGpDispSymbol != NULL) 474 m_pGpDispSymbol->setValue(m_pGOT->getGPDispAddress()); 475 476 return true; 477} 478 479/// allocateCommonSymbols - allocate common symbols in the corresponding 480/// sections. This is called at pre-layout stage. 481/// FIXME: Mips needs to allocate small common symbol 482bool MipsGNULDBackend::allocateCommonSymbols(Module& pModule) { 483 SymbolCategory& symbol_list = pModule.getSymbolTable(); 484 485 if (symbol_list.emptyCommons() && symbol_list.emptyFiles() && 486 symbol_list.emptyLocals() && symbol_list.emptyLocalDyns()) 487 return true; 488 489 SymbolCategory::iterator com_sym, com_end; 490 491 // FIXME: If the order of common symbols is defined, then sort common symbols 492 // std::sort(com_sym, com_end, some kind of order); 493 494 // get corresponding BSS LDSection 495 ELFFileFormat* file_format = getOutputFormat(); 496 LDSection& bss_sect = file_format->getBSS(); 497 LDSection& tbss_sect = file_format->getTBSS(); 498 499 // get or create corresponding BSS SectionData 500 SectionData* bss_sect_data = NULL; 501 if (bss_sect.hasSectionData()) 502 bss_sect_data = bss_sect.getSectionData(); 503 else 504 bss_sect_data = IRBuilder::CreateSectionData(bss_sect); 505 506 SectionData* tbss_sect_data = NULL; 507 if (tbss_sect.hasSectionData()) 508 tbss_sect_data = tbss_sect.getSectionData(); 509 else 510 tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect); 511 512 // remember original BSS size 513 uint64_t bss_offset = bss_sect.size(); 514 uint64_t tbss_offset = tbss_sect.size(); 515 516 // allocate all local common symbols 517 com_end = symbol_list.localEnd(); 518 519 for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) { 520 if (ResolveInfo::Common == (*com_sym)->desc()) { 521 // We have to reset the description of the symbol here. When doing 522 // incremental linking, the output relocatable object may have common 523 // symbols. Therefore, we can not treat common symbols as normal symbols 524 // when emitting the regular name pools. We must change the symbols' 525 // description here. 526 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define); 527 Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size()); 528 529 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) { 530 // allocate TLS common symbol in tbss section 531 tbss_offset += ObjectBuilder::AppendFragment( 532 *frag, *tbss_sect_data, (*com_sym)->value()); 533 ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value()); 534 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0)); 535 } else { 536 // FIXME: how to identify small and large common symbols? 537 bss_offset += ObjectBuilder::AppendFragment( 538 *frag, *bss_sect_data, (*com_sym)->value()); 539 ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value()); 540 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0)); 541 } 542 } 543 } 544 545 // allocate all global common symbols 546 com_end = symbol_list.commonEnd(); 547 for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) { 548 // We have to reset the description of the symbol here. When doing 549 // incremental linking, the output relocatable object may have common 550 // symbols. Therefore, we can not treat common symbols as normal symbols 551 // when emitting the regular name pools. We must change the symbols' 552 // description here. 553 (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define); 554 Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size()); 555 556 if (ResolveInfo::ThreadLocal == (*com_sym)->type()) { 557 // allocate TLS common symbol in tbss section 558 tbss_offset += ObjectBuilder::AppendFragment( 559 *frag, *tbss_sect_data, (*com_sym)->value()); 560 ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value()); 561 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0)); 562 } else { 563 // FIXME: how to identify small and large common symbols? 564 bss_offset += ObjectBuilder::AppendFragment( 565 *frag, *bss_sect_data, (*com_sym)->value()); 566 ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value()); 567 (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0)); 568 } 569 } 570 571 bss_sect.setSize(bss_offset); 572 tbss_sect.setSize(tbss_offset); 573 symbol_list.changeCommonsToGlobal(); 574 return true; 575} 576 577uint64_t MipsGNULDBackend::getGP0(const Input& pInput) const { 578 return m_GP0Map.lookup(&pInput); 579} 580 581void MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) { 582 // If we do not reserve any GOT entries, we do not need to re-define GOT 583 // symbol. 584 if (!m_pGOT->hasGOT1()) 585 return; 586 587 // define symbol _GLOBAL_OFFSET_TABLE_ 588 if (m_pGOTSymbol != NULL) { 589 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 590 "_GLOBAL_OFFSET_TABLE_", 591 ResolveInfo::Object, 592 ResolveInfo::Define, 593 ResolveInfo::Local, 594 0x0, // size 595 0x0, // value 596 FragmentRef::Create(*(m_pGOT->begin()), 0x0), 597 ResolveInfo::Hidden); 598 } else { 599 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 600 "_GLOBAL_OFFSET_TABLE_", 601 ResolveInfo::Object, 602 ResolveInfo::Define, 603 ResolveInfo::Local, 604 0x0, // size 605 0x0, // value 606 FragmentRef::Create(*(m_pGOT->begin()), 0x0), 607 ResolveInfo::Hidden); 608 } 609} 610 611void MipsGNULDBackend::defineGOTPLTSymbol(IRBuilder& pBuilder) { 612 // define symbol _PROCEDURE_LINKAGE_TABLE_ 613 if (m_pPLTSymbol != NULL) { 614 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 615 "_PROCEDURE_LINKAGE_TABLE_", 616 ResolveInfo::Object, 617 ResolveInfo::Define, 618 ResolveInfo::Local, 619 0x0, // size 620 0x0, // value 621 FragmentRef::Create(*(m_pPLT->begin()), 0x0), 622 ResolveInfo::Hidden); 623 } else { 624 m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 625 "_PROCEDURE_LINKAGE_TABLE_", 626 ResolveInfo::Object, 627 ResolveInfo::Define, 628 ResolveInfo::Local, 629 0x0, // size 630 0x0, // value 631 FragmentRef::Create(*(m_pPLT->begin()), 0x0), 632 ResolveInfo::Hidden); 633 } 634} 635 636/// doCreateProgramHdrs - backend can implement this function to create the 637/// target-dependent segments 638void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule) { 639 // TODO 640} 641 642bool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel) { 643 uint64_t sym_value = 0x0; 644 645 LDSymbol* symbol = pRel.symInfo()->outSymbol(); 646 if (symbol->hasFragRef()) { 647 uint64_t value = symbol->fragRef()->getOutputOffset(); 648 uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr(); 649 sym_value = addr + value; 650 } 651 652 Stub* stub = getStubFactory()->create( 653 pRel, sym_value, pBuilder, *getBRIslandFactory()); 654 655 if (stub == NULL) 656 return false; 657 658 assert(stub->symInfo() != NULL); 659 // increase the size of .symtab and .strtab 660 LDSection& symtab = getOutputFormat()->getSymTab(); 661 LDSection& strtab = getOutputFormat()->getStrTab(); 662 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym)); 663 strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1); 664 665 return true; 666} 667 668bool MipsGNULDBackend::doRelax(Module& pModule, 669 IRBuilder& pBuilder, 670 bool& pFinished) { 671 assert(getStubFactory() != NULL && getBRIslandFactory() != NULL); 672 673 bool isRelaxed = false; 674 675 for (Module::obj_iterator input = pModule.obj_begin(); 676 input != pModule.obj_end(); 677 ++input) { 678 LDContext* context = (*input)->context(); 679 680 for (LDContext::sect_iterator rs = context->relocSectBegin(); 681 rs != context->relocSectEnd(); 682 ++rs) { 683 LDSection* sec = *rs; 684 685 if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData()) 686 continue; 687 688 for (RelocData::iterator reloc = sec->getRelocData()->begin(); 689 reloc != sec->getRelocData()->end(); 690 ++reloc) { 691 if (llvm::ELF::R_MIPS_26 != reloc->type()) 692 continue; 693 694 if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc))) 695 isRelaxed = true; 696 } 697 } 698 } 699 700 SectionData* textData = getOutputFormat()->getText().getSectionData(); 701 702 // find the first fragment w/ invalid offset due to stub insertion 703 Fragment* invalid = NULL; 704 pFinished = true; 705 for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(), 706 ie = getBRIslandFactory()->end(); 707 ii != ie; 708 ++ii) { 709 BranchIsland& island = *ii; 710 if (island.end() == textData->end()) 711 break; 712 713 Fragment* exit = island.end(); 714 if ((island.offset() + island.size()) > exit->getOffset()) { 715 invalid = exit; 716 pFinished = false; 717 break; 718 } 719 } 720 721 // reset the offset of invalid fragments 722 while (invalid != NULL) { 723 invalid->setOffset(invalid->getPrevNode()->getOffset() + 724 invalid->getPrevNode()->size()); 725 invalid = invalid->getNextNode(); 726 } 727 728 // reset the size of .text 729 if (isRelaxed) 730 getOutputFormat()->getText().setSize(textData->back().getOffset() + 731 textData->back().size()); 732 733 return isRelaxed; 734} 735 736bool MipsGNULDBackend::initTargetStubs() { 737 if (getStubFactory() == NULL) 738 return false; 739 740 getStubFactory()->addPrototype(new MipsLA25Stub(*this)); 741 return true; 742} 743 744bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel, 745 Relocation::Type& pType, 746 uint32_t& pSymIdx, 747 uint32_t& pOffset) const { 748 return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset); 749} 750 751bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel, 752 Relocation::Type& pType, 753 uint32_t& pSymIdx, 754 uint32_t& pOffset, 755 int32_t& pAddend) const { 756 return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset, pAddend); 757} 758 759bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel, 760 Relocation::Type& pType, 761 uint32_t& pSymIdx, 762 uint64_t& pOffset) const { 763 uint64_t r_info = 0x0; 764 if (llvm::sys::IsLittleEndianHost) { 765 pOffset = pRel.r_offset; 766 r_info = pRel.r_info; 767 } else { 768 pOffset = mcld::bswap64(pRel.r_offset); 769 r_info = mcld::bswap64(pRel.r_info); 770 } 771 772 // MIPS 64 little endian (we do not support big endian now) 773 // has a "special" encoding of r_info relocation 774 // field. Instead of one 64 bit little endian number, it is a little 775 // endian 32 bit number followed by a 32 bit big endian number. 776 pType = mcld::bswap32(r_info >> 32); 777 pSymIdx = r_info & 0xffffffff; 778 return true; 779} 780 781bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel, 782 Relocation::Type& pType, 783 uint32_t& pSymIdx, 784 uint64_t& pOffset, 785 int64_t& pAddend) const { 786 uint64_t r_info = 0x0; 787 if (llvm::sys::IsLittleEndianHost) { 788 pOffset = pRel.r_offset; 789 r_info = pRel.r_info; 790 pAddend = pRel.r_addend; 791 } else { 792 pOffset = mcld::bswap64(pRel.r_offset); 793 r_info = mcld::bswap64(pRel.r_info); 794 pAddend = mcld::bswap64(pRel.r_addend); 795 } 796 797 pType = mcld::bswap32(r_info >> 32); 798 pSymIdx = r_info & 0xffffffff; 799 return true; 800} 801 802void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel, 803 Relocation::Type pType, 804 uint32_t pSymIdx, 805 uint32_t pOffset) const { 806 GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset); 807} 808 809void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel, 810 Relocation::Type pType, 811 uint32_t pSymIdx, 812 uint32_t pOffset, 813 int32_t pAddend) const { 814 GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset, pAddend); 815} 816 817void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel, 818 Relocation::Type pType, 819 uint32_t pSymIdx, 820 uint64_t pOffset) const { 821 uint64_t r_info = mcld::bswap32(pType); 822 r_info <<= 32; 823 r_info |= pSymIdx; 824 825 pRel.r_info = r_info; 826 pRel.r_offset = pOffset; 827} 828 829void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel, 830 Relocation::Type pType, 831 uint32_t pSymIdx, 832 uint64_t pOffset, 833 int64_t pAddend) const { 834 uint64_t r_info = mcld::bswap32(pType); 835 r_info <<= 32; 836 r_info |= pSymIdx; 837 838 pRel.r_info = r_info; 839 pRel.r_offset = pOffset; 840 pRel.r_addend = pAddend; 841} 842 843//===----------------------------------------------------------------------===// 844// Mips32GNULDBackend 845//===----------------------------------------------------------------------===// 846Mips32GNULDBackend::Mips32GNULDBackend(const LinkerConfig& pConfig, 847 MipsGNUInfo* pInfo) 848 : MipsGNULDBackend(pConfig, pInfo) { 849} 850 851bool Mips32GNULDBackend::initRelocator() { 852 if (m_pRelocator == NULL) 853 m_pRelocator = new Mips32Relocator(*this, config()); 854 855 return true; 856} 857 858void Mips32GNULDBackend::initTargetSections(Module& pModule, 859 ObjectBuilder& pBuilder) { 860 MipsGNULDBackend::initTargetSections(pModule, pBuilder); 861 862 if (LinkerConfig::Object == config().codeGenType()) 863 return; 864 865 ELFFileFormat* fileFormat = getOutputFormat(); 866 867 // initialize .got 868 LDSection& got = fileFormat->getGOT(); 869 m_pGOT = new Mips32GOT(got); 870 871 // initialize .got.plt 872 LDSection& gotplt = fileFormat->getGOTPLT(); 873 m_pGOTPLT = new MipsGOTPLT(gotplt); 874 875 // initialize .plt 876 LDSection& plt = fileFormat->getPLT(); 877 m_pPLT = new MipsPLT(plt); 878} 879 880size_t Mips32GNULDBackend::getRelEntrySize() { 881 return 8; 882} 883 884size_t Mips32GNULDBackend::getRelaEntrySize() { 885 return 12; 886} 887 888//===----------------------------------------------------------------------===// 889// Mips64GNULDBackend 890//===----------------------------------------------------------------------===// 891Mips64GNULDBackend::Mips64GNULDBackend(const LinkerConfig& pConfig, 892 MipsGNUInfo* pInfo) 893 : MipsGNULDBackend(pConfig, pInfo) { 894} 895 896bool Mips64GNULDBackend::initRelocator() { 897 if (m_pRelocator == NULL) 898 m_pRelocator = new Mips64Relocator(*this, config()); 899 900 return true; 901} 902 903void Mips64GNULDBackend::initTargetSections(Module& pModule, 904 ObjectBuilder& pBuilder) { 905 MipsGNULDBackend::initTargetSections(pModule, pBuilder); 906 907 if (LinkerConfig::Object == config().codeGenType()) 908 return; 909 910 ELFFileFormat* fileFormat = getOutputFormat(); 911 912 // initialize .got 913 LDSection& got = fileFormat->getGOT(); 914 m_pGOT = new Mips64GOT(got); 915 916 // initialize .got.plt 917 LDSection& gotplt = fileFormat->getGOTPLT(); 918 m_pGOTPLT = new MipsGOTPLT(gotplt); 919 920 // initialize .plt 921 LDSection& plt = fileFormat->getPLT(); 922 m_pPLT = new MipsPLT(plt); 923} 924 925size_t Mips64GNULDBackend::getRelEntrySize() { 926 return 16; 927} 928 929size_t Mips64GNULDBackend::getRelaEntrySize() { 930 return 24; 931} 932 933//===----------------------------------------------------------------------===// 934/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend 935/// 936static TargetLDBackend* createMipsLDBackend(const LinkerConfig& pConfig) { 937 const llvm::Triple& triple = pConfig.targets().triple(); 938 939 if (triple.isOSDarwin()) { 940 assert(0 && "MachO linker is not supported yet"); 941 } 942 if (triple.isOSWindows()) { 943 assert(0 && "COFF linker is not supported yet"); 944 } 945 946 llvm::Triple::ArchType arch = triple.getArch(); 947 948 if (llvm::Triple::mips64el == arch) 949 return new Mips64GNULDBackend(pConfig, new MipsGNUInfo(triple)); 950 951 assert(arch == llvm::Triple::mipsel); 952 return new Mips32GNULDBackend(pConfig, new MipsGNUInfo(triple)); 953} 954 955} // namespace mcld 956 957//===----------------------------------------------------------------------===// 958// Force static initialization. 959//===----------------------------------------------------------------------===// 960extern "C" void MCLDInitializeMipsLDBackend() { 961 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget, 962 mcld::createMipsLDBackend); 963 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMips64elTarget, 964 mcld::createMipsLDBackend); 965} 966