15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- MipsLDBackend.cpp --------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
9cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "Mips.h"
10d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsGNUInfo.h"
11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "MipsELFDynamic.h"
1287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "MipsLA25Stub.h"
13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "MipsLDBackend.h"
14d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsRelocator.h"
15cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Triple.h>
1787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/Support/Casting.h>
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
1987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/Support/Host.h>
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Module.h>
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LinkerConfig.h>
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/IRBuilder.h>
2487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LD/BranchIslandFactory.h>
2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LD/LDContext.h>
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LD/StubFactory.h>
2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LD/ELFFileFormat.h>
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/MC/Attribute.h>
2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FillFragment.h>
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h>
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/MemoryArea.h>
32affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/TargetRegistry.h>
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/OutputRelocSection.h>
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Object/ObjectBuilder.h>
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaousing namespace mcld;
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// MipsGNULDBackend
4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
42d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig,
43d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                   MipsGNUInfo* pInfo)
44d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  : GNULDBackend(pConfig, pInfo),
45d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_pRelocator(NULL),
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pGOT(NULL),
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pPLT(NULL),
4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pGOTPLT(NULL),
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pInfo(*pInfo),
5087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pRelPlt(NULL),
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pRelDyn(NULL),
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pDynamic(NULL),
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pGOTSymbol(NULL),
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pPLTSymbol(NULL),
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pGpDispSymbol(NULL)
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsGNULDBackend::~MipsGNULDBackend()
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
61d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  delete m_pRelocator;
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  delete m_pPLT;
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  delete m_pRelPlt;
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pRelDyn;
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pDynamic;
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::needsLA25Stub(Relocation::Type pType,
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     const mcld::ResolveInfo* pSym)
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (config().isCodeIndep())
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::ELF::R_MIPS_26 != pType)
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSym->isLocal())
7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::addNonPICBranchSym(ResolveInfo* rsym)
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_HasNonPICBranchSyms.insert(rsym);
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::hasNonPICBranch(const ResolveInfo* rsym) const
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return m_HasNonPICBranchSyms.count(rsym);
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::initTargetSections(Module& pModule,
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                            ObjectBuilder& pBuilder)
9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object == config().codeGenType())
9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat* file_format = getOutputFormat();
10087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .rel.plt
10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& relplt = file_format->getRelPlt();
10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pRelPlt = new OutputRelocSection(pModule, relplt);
10487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .rel.dyn
10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& reldyn = file_format->getRelDyn();
10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pRelDyn = new OutputRelocSection(pModule, reldyn);
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid MipsGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // same name in input
1146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   "_GLOBAL_OFFSET_TABLE_",
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Object,
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Define,
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Local,
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   0x0,  // size
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   0x0,  // value
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                   FragmentRef::Null(), // FragRef
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Hidden);
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Define the symbol _PROCEDURE_LINKAGE_TABLE_ if there is a symbol with the
12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // same name in input
12687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pPLTSymbol =
12787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
12887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   "_PROCEDURE_LINKAGE_TABLE_",
12987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   ResolveInfo::Object,
13087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   ResolveInfo::Define,
13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   ResolveInfo::Local,
13287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   0x0,  // size
13387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   0x0,  // value
13487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   FragmentRef::Null(), // FragRef
13587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   ResolveInfo::Hidden);
13687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_pGpDispSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   "_gp_disp",
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Section,
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Define,
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Absolute,
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   0x0,  // size
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   0x0,  // value
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                   FragmentRef::Null(), // FragRef
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Default);
146a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>(
147a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                   "_gp",
148a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                   ResolveInfo::NoType,
149a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                   ResolveInfo::Define,
150a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                   ResolveInfo::Absolute,
151a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                   0x0,  // size
152a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                   0x0,  // value
153a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                   FragmentRef::Null(), // FragRef
154a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                   ResolveInfo::Default);
155a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines}
156a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines
157a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hinesconst Relocator* MipsGNULDBackend::getRelocator() const
158a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines{
159a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  assert(NULL != m_pRelocator);
160a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  return m_pRelocator;
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
163d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator* MipsGNULDBackend::getRelocator()
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
165d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  assert(NULL != m_pRelocator);
166d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return m_pRelocator;
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid MipsGNULDBackend::doPreLayout(IRBuilder& pBuilder)
170cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
1716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // initialize .dynamic data
1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!config().isCodeStatic() && NULL == m_pDynamic)
1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pDynamic = new MipsELFDynamic(*this, config());
174cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set .got size
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // when building shared object, the .got section is must.
17722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Object != config().codeGenType()) {
17822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (LinkerConfig::DynObj == config().codeGenType() ||
17922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        m_pGOT->hasGOT1() ||
18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        NULL != m_pGOTSymbol) {
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      m_pGOT->finalizeScanning(*m_pRelDyn);
18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_pGOT->finalizeSectionSize();
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      defineGOTSymbol(pBuilder);
18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
18622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
18787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (m_pGOTPLT->hasGOT1()) {
18887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_pGOTPLT->finalizeSectionSize();
18987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
19087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      defineGOTPLTSymbol(pBuilder);
19187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
19287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
19387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (m_pPLT->hasPLT1())
19487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_pPLT->finalizeSectionSize();
19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
196d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    ELFFileFormat* file_format = getOutputFormat();
19787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
19887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // set .rel.plt size
19987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (!m_pRelPlt->empty()) {
20087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      assert(!config().isCodeStatic() &&
20187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            "static linkage should not result in a dynamic relocation section");
20287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      file_format->getRelPlt().setSize(
20387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                  m_pRelPlt->numOfRelocs() * getRelEntrySize());
20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set .rel.dyn size
2076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!m_pRelDyn->empty()) {
2086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(!config().isCodeStatic() &&
2096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines            "static linkage should not result in a dynamic relocation section");
210d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      file_format->getRelDyn().setSize(
211d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                  m_pRelDyn->numOfRelocs() * getRelEntrySize());
2126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid MipsGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
21887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const ELFFileFormat *format = getOutputFormat();
21987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
22087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (format->hasGOTPLT()) {
22187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(m_pGOTPLT && "doPostLayout failed, m_pGOTPLT is NULL!");
22287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pGOTPLT->applyAllGOTPLT(m_pPLT->addr());
22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
22487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
22587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (format->hasPLT()) {
22687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(m_pPLT && "doPostLayout failed, m_pPLT is NULL!");
22787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pPLT->applyAllPLT(*m_pGOTPLT);
22887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
22987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pInfo.setABIVersion(m_pPLT && m_pPLT->hasPLT1() ? 1 : 0);
23187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME: (simon) We need to iterate all input sections
23387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // check that flags are consistent and merge them properly.
23487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t picFlags = llvm::ELF::EF_MIPS_CPIC;
23587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (config().targets().triple().isArch64Bit()) {
23687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    picFlags |= llvm::ELF::EF_MIPS_PIC;
23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
23987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (LinkerConfig::DynObj == config().codeGenType())
24087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      picFlags |= llvm::ELF::EF_MIPS_PIC;
24187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pInfo.setPICFlags(picFlags);
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsELFDynamic& MipsGNULDBackend::dynamic()
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(NULL != m_pDynamic);
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst MipsELFDynamic& MipsGNULDBackend::dynamic() const
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(NULL != m_pDynamic);
2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
26222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaouint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection,
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           MemoryRegion& pRegion) const
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pRegion.size() && "Size of MemoryRegion is zero!");
2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
26722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const ELFFileFormat* file_format = getOutputFormat();
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
26987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
27087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_pGOT->emit(pRegion);
27187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
27287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
27387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_pPLT->emit(pRegion);
27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
27687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
27787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
27887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_pGOTPLT->emit(pRegion);
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
281affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  fatal(diag::unrecognized_output_sectoin)
282affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          << pSection.name()
283affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          << "mclinker@googlegroups.com";
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0;
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesbool MipsGNULDBackend::hasEntryInStrTab(const LDSymbol& pSym) const
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return ResolveInfo::Section != pSym.type() ||
290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         m_pGpDispSymbol == &pSym;
291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
29222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesnamespace {
294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  struct DynsymGOTCompare
295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  {
296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    const MipsGOT& m_pGOT;
29722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
298f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    DynsymGOTCompare(const MipsGOT& pGOT)
299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      : m_pGOT(pGOT)
300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    {
30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bool operator()(const LDSymbol* X, const LDSymbol* Y) const
304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    {
305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return m_pGOT.dynSymOrderCompare(X, Y);
30622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  };
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
310f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid MipsGNULDBackend::orderSymbolTable(Module& pModule)
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (GeneralOptions::GNU  == config().options().getHashStyle() ||
313f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      GeneralOptions::Both == config().options().getHashStyle()) {
314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // The MIPS ABI and .gnu.hash require .dynsym to be sorted
315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // in different ways. The MIPS ABI requires a mapping between
316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // the GOT and the symbol table. At the same time .gnu.hash
317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // needs symbols to be grouped by hash code.
318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    llvm::errs() << ".gnu.hash is incompatible with the MIPS ABI\n";
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Module::SymbolTable& symbols = pModule.getSymbolTable();
3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::stable_sort(symbols.dynamicBegin(), symbols.dynamicEnd(),
324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   DynsymGOTCompare(*m_pGOT));
3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
32787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace llvm {
32887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace ELF {
32987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// SHT_MIPS_OPTIONS section's block descriptor.
33087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstruct Elf_Options {
33187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  unsigned char kind;     // Determines interpretation of variable
33287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                          // part of descriptor. See ODK_xxx enumeration.
33387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  unsigned char size;     // Byte size of descriptor, including this header.
33487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf64_Half    section;  // Section header index of section affected,
33587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                          // or 0 for global options.
33687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf64_Word    info;     // Kind-specific information.
33787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
33887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
33987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Type of SHT_MIPS_OPTIONS section's block.
34087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesenum {
34187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_NULL       = 0, // Undefined.
34287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_REGINFO    = 1, // Register usage and GP value.
34387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_EXCEPTIONS = 2, // Exception processing information.
34487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_PAD        = 3, // Section padding information.
34587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_HWPATCH    = 4, // Hardware workarounds performed.
34687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_FILL       = 5, // Fill value used by the linker.
34787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_TAGS       = 6, // Reserved space for desktop tools.
34887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_HWAND      = 7, // Hardware workarounds, AND bits when merging.
34987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_HWOR       = 8, // Hardware workarounds, OR bits when merging.
35087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_GP_GROUP   = 9, // GP group to use for text/data sections.
35187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ODK_IDENT      = 10 // ID information.
35287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
35387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
35487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 32 bit ABI.
35587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstruct Elf32_RegInfo {
35687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf32_Word ri_gprmask;    // Mask of general purpose registers used.
35787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used.
35887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf32_Addr ri_gp_value;   // GP register value for this object file.
35987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
36087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
36187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 64 bit ABI.
36287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstruct Elf64_RegInfo {
36387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf32_Word ri_gprmask;    // Mask of general purpose registers used.
36487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf32_Word ri_pad;        // Padding.
36587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used.
36687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Elf64_Addr ri_gp_value;   // GP register value for this object file.
36787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
36887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
36987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
37087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
37187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
37287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readSection(Input& pInput, SectionData& pSD)
37387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
37487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef name(pSD.getSection().name());
37587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
37687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (name.startswith(".sdata")) {
37787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
37887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t size = pSD.getSection().size();
37987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
38087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
38187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ObjectBuilder::AppendFragment(*frag, pSD);
38287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
38387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
38487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
38587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSD.getSection().type() == llvm::ELF::SHT_MIPS_OPTIONS) {
38687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
38787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint32_t size = pSD.getSection().size();
38887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
38987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    llvm::StringRef region = pInput.memArea()->request(offset, size);
39087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (region.size() > 0) {
39187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      const llvm::ELF::Elf_Options* optb =
39287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin());
39387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      const llvm::ELF::Elf_Options* opte =
39487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin() + size);
39587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
39687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      for (const llvm::ELF::Elf_Options* opt = optb; opt < opte; opt += opt->size) {
39787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        switch (opt->kind) {
39887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          default:
39987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // Nothing to do.
40087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            break;
40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          case llvm::ELF::ODK_REGINFO:
40287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            if (config().targets().triple().isArch32Bit()) {
40387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              const llvm::ELF::Elf32_RegInfo* reg =
40487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                reinterpret_cast<const llvm::ELF::Elf32_RegInfo*>(opt + 1);
40587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              m_GP0Map[&pInput] = reg->ri_gp_value;
40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            }
40787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            else {
40887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              const llvm::ELF::Elf64_RegInfo* reg =
40987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                reinterpret_cast<const llvm::ELF::Elf64_RegInfo*>(opt + 1);
41087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              m_GP0Map[&pInput] = reg->ri_gp_value;
41187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            }
41287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            break;
41387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
41487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
41587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
41687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
41787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
41887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
41987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
42087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return GNULDBackend::readSection(pInput, pSD);
42187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
42287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsGOT& MipsGNULDBackend::getGOT()
4245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pGOT);
4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
4275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst MipsGOT& MipsGNULDBackend::getGOT() const
4305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pGOT);
4325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
4335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
43587f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsPLT& MipsGNULDBackend::getPLT()
43687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
43787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != m_pPLT);
43887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pPLT;
43987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
44087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesconst MipsPLT& MipsGNULDBackend::getPLT() const
44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
44387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != m_pPLT);
44487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pPLT;
44587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
44687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
44787f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMipsGOTPLT& MipsGNULDBackend::getGOTPLT()
44887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
44987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != m_pGOTPLT);
45087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pGOTPLT;
45187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
45287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
45387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesconst MipsGOTPLT& MipsGNULDBackend::getGOTPLT() const
45487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
45587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != m_pGOTPLT);
45687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pGOTPLT;
45787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
45887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
45987f34658dec9097d987d254a990ea7f311bfc95fStephen HinesOutputRelocSection& MipsGNULDBackend::getRelPLT()
46087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
46187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != m_pRelPlt);
46287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pRelPlt;
46387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
46487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
46587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesconst OutputRelocSection& MipsGNULDBackend::getRelPLT() const
46687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
46787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != m_pRelPlt);
46887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pRelPlt;
46987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
47087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoOutputRelocSection& MipsGNULDBackend::getRelDyn()
4725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pRelDyn);
4745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelDyn;
4755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst OutputRelocSection& MipsGNULDBackend::getRelDyn() const
4785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pRelDyn);
4805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelDyn;
4815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaounsigned int
48422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoMipsGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
4855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
48622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const ELFFileFormat* file_format = getOutputFormat();
4875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
48887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT()))
48987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return SHO_DATA;
49087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
49187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
4925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return SHO_DATA;
4935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
49587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return SHO_PLT;
49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return SHO_UNDEFINED;
4985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// finalizeSymbol - finalize the symbol value
5016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool MipsGNULDBackend::finalizeTargetSymbols()
5025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
503cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (NULL != m_pGpDispSymbol)
504f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pGpDispSymbol->setValue(m_pGOT->getGPDispAddress());
505f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
506affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
5075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// allocateCommonSymbols - allocate common symbols in the corresponding
51022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// sections. This is called at pre-layout stage.
5115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// @refer Google gold linker: common.cc: 214
5125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// FIXME: Mips needs to allocate small common symbol
51322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool MipsGNULDBackend::allocateCommonSymbols(Module& pModule)
5145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
51522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SymbolCategory& symbol_list = pModule.getSymbolTable();
5165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (symbol_list.emptyCommons() && symbol_list.emptyFiles() &&
5186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      symbol_list.emptyLocals() && symbol_list.emptyLocalDyns())
5195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return true;
5205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
521affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  SymbolCategory::iterator com_sym, com_end;
5225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // FIXME: If the order of common symbols is defined, then sort common symbols
5245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // std::sort(com_sym, com_end, some kind of order);
5255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
52622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get corresponding BSS LDSection
52722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ELFFileFormat* file_format = getOutputFormat();
52822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& bss_sect = file_format->getBSS();
52922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& tbss_sect = file_format->getTBSS();
5305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
531cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // get or create corresponding BSS SectionData
53222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData* bss_sect_data = NULL;
53322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (bss_sect.hasSectionData())
53422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    bss_sect_data = bss_sect.getSectionData();
53522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
53622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
53722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
53822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData* tbss_sect_data = NULL;
53922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (tbss_sect.hasSectionData())
54022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    tbss_sect_data = tbss_sect.getSectionData();
54122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
54222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
5435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
544affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // remember original BSS size
54522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t bss_offset  = bss_sect.size();
54622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t tbss_offset = tbss_sect.size();
5475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // allocate all local common symbols
5495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  com_end = symbol_list.localEnd();
550affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
5515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
5525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (ResolveInfo::Common == (*com_sym)->desc()) {
5535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // We have to reset the description of the symbol here. When doing
5545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // incremental linking, the output relocatable object may have common
5555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // symbols. Therefore, we can not treat common symbols as normal symbols
5565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // when emitting the regular name pools. We must change the symbols'
5575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // description here.
5585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
559cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
560affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
561affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
562affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // allocate TLS common symbol in tbss section
56322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        tbss_offset += ObjectBuilder::AppendFragment(*frag,
56422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                     *tbss_sect_data,
56522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                     (*com_sym)->value());
566551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
56787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
568affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
569affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // FIXME: how to identify small and large common symbols?
570affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      else {
57122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        bss_offset += ObjectBuilder::AppendFragment(*frag,
57222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    *bss_sect_data,
57322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    (*com_sym)->value());
574551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
57587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
576affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
5775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
5785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // allocate all global common symbols
5815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  com_end = symbol_list.commonEnd();
5825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
5835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // We have to reset the description of the symbol here. When doing
5845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // incremental linking, the output relocatable object may have common
5855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // symbols. Therefore, we can not treat common symbols as normal symbols
5865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // when emitting the regular name pools. We must change the symbols'
5875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // description here.
5885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
589cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
590affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
591affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
592affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // allocate TLS common symbol in tbss section
59322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      tbss_offset += ObjectBuilder::AppendFragment(*frag,
59422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                   *tbss_sect_data,
59522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                   (*com_sym)->value());
596551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
59787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
598affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
599affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // FIXME: how to identify small and large common symbols?
600affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    else {
60122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      bss_offset += ObjectBuilder::AppendFragment(*frag,
60222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                  *bss_sect_data,
60322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                  (*com_sym)->value());
604551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
60587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
606affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
6075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
60922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bss_sect.setSize(bss_offset);
61022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  tbss_sect.setSize(tbss_offset);
6115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symbol_list.changeCommonsToGlobal();
6125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
6135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
61587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesuint64_t MipsGNULDBackend::getGP0(const Input& pInput) const
61687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
61787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return m_GP0Map.lookup(&pInput);
61887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
61987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
6215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
622f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // If we do not reserve any GOT entries, we do not need to re-define GOT
623f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // symbol.
624f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!m_pGOT->hasGOT1())
625f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
626f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
62722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // define symbol _GLOBAL_OFFSET_TABLE_
628affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if ( m_pGOTSymbol != NULL ) {
6296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
6305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     "_GLOBAL_OFFSET_TABLE_",
6315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Object,
6325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Define,
6335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Local,
6345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     0x0, // size
6355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     0x0, // value
63622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                     FragmentRef::Create(*(m_pGOT->begin()), 0x0),
6375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Hidden);
6385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
6406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
6415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     "_GLOBAL_OFFSET_TABLE_",
6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Object,
6435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Define,
6445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Local,
6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     0x0, // size
6465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     0x0, // value
64722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                     FragmentRef::Create(*(m_pGOT->begin()), 0x0),
6485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Hidden);
6495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
65287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::defineGOTPLTSymbol(IRBuilder& pBuilder)
65387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
65487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // define symbol _PROCEDURE_LINKAGE_TABLE_
65587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ( m_pPLTSymbol != NULL ) {
65687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
65787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     "_PROCEDURE_LINKAGE_TABLE_",
65887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     ResolveInfo::Object,
65987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     ResolveInfo::Define,
66087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     ResolveInfo::Local,
66187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     0x0, // size
66287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     0x0, // value
66387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     FragmentRef::Create(*(m_pPLT->begin()), 0x0),
66487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     ResolveInfo::Hidden);
66587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
66687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
66787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
66887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     "_PROCEDURE_LINKAGE_TABLE_",
66987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     ResolveInfo::Object,
67087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     ResolveInfo::Define,
67187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     ResolveInfo::Local,
67287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     0x0, // size
67387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     0x0, // value
67487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     FragmentRef::Create(*(m_pPLT->begin()), 0x0),
67587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                     ResolveInfo::Hidden);
67687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
67787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
67887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
67922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// doCreateProgramHdrs - backend can implement this function to create the
68022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// target-dependent segments
6816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid MipsGNULDBackend::doCreateProgramHdrs(Module& pModule)
6825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
68322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // TODO
6845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
68687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel)
68787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
68887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t sym_value = 0x0;
68987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
69087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSymbol* symbol = pRel.symInfo()->outSymbol();
69187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (symbol->hasFragRef()) {
69287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t value = symbol->fragRef()->getOutputOffset();
69387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr();
69487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    sym_value = addr + value;
69587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
69687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
69787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Stub* stub =
69887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    getStubFactory()->create(pRel, sym_value, pBuilder, *getBRIslandFactory());
69987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
70087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL == stub)
70187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
70287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
70387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != stub->symInfo());
70487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // increase the size of .symtab and .strtab
70587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& symtab = getOutputFormat()->getSymTab();
70687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& strtab = getOutputFormat()->getStrTab();
70787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
70887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
70987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
71087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
71187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
71287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
71387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder,
71487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               bool& pFinished)
71587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
71687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != getStubFactory() && NULL != getBRIslandFactory());
71787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
71887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bool isRelaxed = false;
71987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
72087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (Module::obj_iterator input = pModule.obj_begin();
72187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines       input != pModule.obj_end(); ++input) {
72287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    LDContext* context = (*input)->context();
72387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
72487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    for (LDContext::sect_iterator rs = context->relocSectBegin();
72587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         rs != context->relocSectEnd(); ++rs) {
72687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      LDSection* sec = *rs;
72787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
72887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData())
72987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        continue;
73087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
73187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      for (RelocData::iterator reloc = sec->getRelocData()->begin();
73287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines           reloc != sec->getRelocData()->end(); ++reloc) {
73387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (llvm::ELF::R_MIPS_26 != reloc->type())
73487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          continue;
73587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
73687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc)))
73787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          isRelaxed = true;
73887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
73987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
74087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
74187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
74287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SectionData* textData = getOutputFormat()->getText().getSectionData();
74387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
74487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // find the first fragment w/ invalid offset due to stub insertion
74587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment* invalid = NULL;
74687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pFinished = true;
74787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(),
74887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     ie = getBRIslandFactory()->end();
74987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines       ii != ie; ++ii)
75087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  {
75187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    BranchIsland& island = *ii;
75287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (island.end() == textData->end())
75387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
75487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
75587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Fragment* exit = island.end();
75687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if ((island.offset() + island.size()) > exit->getOffset()) {
75787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      invalid = exit;
75887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pFinished = false;
75987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
76087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
76187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
76287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
76387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // reset the offset of invalid fragments
76487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  while (NULL != invalid) {
76587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    invalid->setOffset(invalid->getPrevNode()->getOffset() +
76687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                       invalid->getPrevNode()->size());
76787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    invalid = invalid->getNextNode();
76887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
76987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // reset the size of .text
77187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (isRelaxed)
77287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    getOutputFormat()->getText().setSize(textData->back().getOffset() +
77387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                         textData->back().size());
77487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return isRelaxed;
77687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
77787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::initTargetStubs()
77987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
78087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL == getStubFactory())
78187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
78287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
78387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  getStubFactory()->addPrototype(new MipsLA25Stub(*this));
78487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
78587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
78687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
78787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel,
78887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type& pType,
78987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pSymIdx,
79087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pOffset) const
79187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
79287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset);
79387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
79487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
79587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel,
79687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type& pType,
79787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pSymIdx,
79887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pOffset,
79987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      int32_t& pAddend) const
80087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
80187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
80287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
80387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
80487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel,
80587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type& pType,
80687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pSymIdx,
80787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint64_t& pOffset) const
80887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
80987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t r_info = 0x0;
81087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::sys::IsLittleEndianHost) {
81187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pOffset = pRel.r_offset;
81287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    r_info  = pRel.r_info;
81387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
81487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
81587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pOffset = mcld::bswap64(pRel.r_offset);
81687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    r_info  = mcld::bswap64(pRel.r_info);
81787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
81887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
81987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // MIPS 64 little endian (we do not support big endian now)
82087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // has a "special" encoding of r_info relocation
82187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // field. Instead of one 64 bit little endian number, it is a little
82287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // endian 32 bit number followed by a 32 bit big endian number.
82387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pType = mcld::bswap32(r_info >> 32);
82487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pSymIdx = r_info & 0xffffffff;
82587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
82687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
82787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
82887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel,
82987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type& pType,
83087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pSymIdx,
83187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint64_t& pOffset,
83287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      int64_t& pAddend) const
83387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
83487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t r_info = 0x0;
83587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::sys::IsLittleEndianHost) {
83687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pOffset = pRel.r_offset;
83787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    r_info  = pRel.r_info;
83887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pAddend = pRel.r_addend;
83987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
84087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
84187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pOffset = mcld::bswap64(pRel.r_offset);
84287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    r_info  = mcld::bswap64(pRel.r_info);
84387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pAddend = mcld::bswap64(pRel.r_addend);
84487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
84587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pType = mcld::bswap32(r_info >> 32);
84787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pSymIdx = r_info & 0xffffffff;
84887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
84987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
85187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel,
85287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type pType,
85387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pSymIdx,
85487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pOffset) const
85587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
85687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset);
85787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
85887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
85987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel,
86087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type pType,
86187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pSymIdx,
86287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pOffset,
86387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      int32_t pAddend) const
86487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
86587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
86687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
86787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
86887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel,
86987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type pType,
87087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pSymIdx,
87187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint64_t pOffset) const
87287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
87387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t r_info = mcld::bswap32(pType);
87487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  r_info <<= 32;
87587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  r_info |= pSymIdx;
87687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
87787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_info = r_info;
87887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_offset = pOffset;
87987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
88087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
88187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel,
88287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type pType,
88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pSymIdx,
88487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint64_t pOffset,
88587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      int64_t pAddend) const
88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
88787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t r_info = mcld::bswap32(pType);
88887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  r_info <<= 32;
88987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  r_info |= pSymIdx;
89087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
89187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_info = r_info;
89287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_offset = pOffset;
89387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_addend = pAddend;
89487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
89587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
89687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
89787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips32GNULDBackend
89887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
89987f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips32GNULDBackend::Mips32GNULDBackend(const LinkerConfig& pConfig,
90087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                       MipsGNUInfo* pInfo)
90187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  : MipsGNULDBackend(pConfig, pInfo)
90287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{}
90387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool Mips32GNULDBackend::initRelocator()
90587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
90687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL == m_pRelocator)
90787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pRelocator = new Mips32Relocator(*this, config());
90887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
90987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
91087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
91187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
91287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid Mips32GNULDBackend::initTargetSections(Module& pModule,
91387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                            ObjectBuilder& pBuilder)
91487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
91587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGNULDBackend::initTargetSections(pModule, pBuilder);
91687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
91787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object == config().codeGenType())
91887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
91987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat* fileFormat = getOutputFormat();
92187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .got
92387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& got = fileFormat->getGOT();
92487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pGOT = new Mips32GOT(got);
92587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .got.plt
92787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& gotplt = fileFormat->getGOTPLT();
92887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pGOTPLT = new MipsGOTPLT(gotplt);
92987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .plt
93187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& plt = fileFormat->getPLT();
93287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pPLT = new MipsPLT(plt);
93387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
93487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinessize_t Mips32GNULDBackend::getRelEntrySize()
93687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
93787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 8;
93887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
93987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
94087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinessize_t Mips32GNULDBackend::getRelaEntrySize()
94187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
94287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 12;
94387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
94487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
94587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
94687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips64GNULDBackend
94787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
94887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips64GNULDBackend::Mips64GNULDBackend(const LinkerConfig& pConfig,
94987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                       MipsGNUInfo* pInfo)
95087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  : MipsGNULDBackend(pConfig, pInfo)
95187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{}
95287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
95387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool Mips64GNULDBackend::initRelocator()
95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
95587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL == m_pRelocator)
95687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pRelocator = new Mips64Relocator(*this, config());
95787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
95887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
95987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
96087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
96187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid Mips64GNULDBackend::initTargetSections(Module& pModule,
96287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                            ObjectBuilder& pBuilder)
96387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
96487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGNULDBackend::initTargetSections(pModule, pBuilder);
96587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
96687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object == config().codeGenType())
96787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
96887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
96987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat* fileFormat = getOutputFormat();
97087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
97187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .got
97287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& got = fileFormat->getGOT();
97387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pGOT = new Mips64GOT(got);
97487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
97587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .got.plt
97687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& gotplt = fileFormat->getGOTPLT();
97787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pGOTPLT = new MipsGOTPLT(gotplt);
97887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
97987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .plt
98087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& plt = fileFormat->getPLT();
98187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pPLT = new MipsPLT(plt);
98287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
98387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
98487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinessize_t Mips64GNULDBackend::getRelEntrySize()
98587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
98687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 16;
98787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
98887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
98987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinessize_t Mips64GNULDBackend::getRelaEntrySize()
99087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
99187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 24;
99287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
99387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
9955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
9965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao///
99787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic TargetLDBackend* createMipsLDBackend(const LinkerConfig& pConfig)
9985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
99987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const llvm::Triple& triple = pConfig.targets().triple();
100087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
100187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (triple.isOSDarwin()) {
10025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "MachO linker is not supported yet");
10035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
100487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (triple.isOSWindows()) {
10055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "COFF linker is not supported yet");
10065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
100787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
100887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::Triple::ArchType arch = triple.getArch();
100987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
101087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::Triple::mips64el == arch)
101187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return new Mips64GNULDBackend(pConfig, new MipsGNUInfo(triple));
101287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
101387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert (arch == llvm::Triple::mipsel);
101487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return new Mips32GNULDBackend(pConfig, new MipsGNUInfo(triple));
10155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
10165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
101722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
10185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Force static initialization.
101922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
102022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoextern "C" void MCLDInitializeMipsLDBackend() {
10215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
102222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                createMipsLDBackend);
102387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMips64elTarget,
102487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                createMipsLDBackend);
10255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1026