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//===----------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "Mips.h"
11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "MipsELFDynamic.h"
12cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "MipsLDBackend.h"
13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "MipsRelocationFactory.h"
14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Triple.h>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
18cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/LD/FillFragment.h>
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/SectionMap.h>
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/MC/MCLDInfo.h>
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/MC/MCLinker.h>
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h>
23affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/TargetRegistry.h>
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/OutputRelocSection.h>
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoenum {
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // The original o32 abi.
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  E_MIPS_ABI_O32    = 0x00001000,
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // O32 extended to work on 64 bit architectures.
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  E_MIPS_ABI_O64    = 0x00002000,
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // EABI in 32 bit mode.
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  E_MIPS_ABI_EABI32 = 0x00003000,
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // EABI in 64 bit mode.
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  E_MIPS_ABI_EABI64 = 0x00004000
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao};
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace mcld {
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsGNULDBackend::MipsGNULDBackend()
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  : m_pRelocFactory(NULL),
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pGOT(NULL),
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pRelDyn(NULL),
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pDynamic(NULL),
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pGOTSymbol(NULL),
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pGpDispSymbol(NULL)
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsGNULDBackend::~MipsGNULDBackend()
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL != m_pRelocFactory)
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    delete m_pRelocFactory;
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL != m_pGOT)
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    delete m_pGOT;
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL != m_pRelDyn)
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    delete m_pRelDyn;
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL != m_pDynamic)
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    delete m_pDynamic;
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MipsGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Nothing to do because we do not support
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // any MIPS specific sections now.
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::initTargetSections(MCLinker& pLinker)
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
73affc150dc44fab1911775a49636d0ce85333b634Zonr Changvoid MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // same name in input
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   "_GLOBAL_OFFSET_TABLE_",
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   false,
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Object,
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Define,
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Local,
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   0x0,  // size
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   0x0,  // value
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   NULL, // FragRef
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Hidden);
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_pGpDispSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   "_gp_disp",
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   false,
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Section,
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Define,
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Absolute,
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   0x0,  // size
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   0x0,  // value
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   NULL, // FragRef
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ResolveInfo::Default);
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL != m_pGpDispSymbol) {
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pGpDispSymbol->resolveInfo()->setReserved(ReserveGpDisp);
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MipsGNULDBackend::initRelocFactory(const MCLinker& pLinker)
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL == m_pRelocFactory) {
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pRelocFactory = new MipsRelocationFactory(1024, *this);
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pRelocFactory->setLayout(pLinker.getLayout());
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocationFactory* MipsGNULDBackend::getRelocFactory()
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pRelocFactory);
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return m_pRelocFactory;
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::scanRelocation(Relocation& pReloc,
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const LDSymbol& pInputSym,
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      MCLinker& pLinker,
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                      const Output& pOutput,
124affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                      const LDSection& pSection)
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
130affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != pSection.getLink());
131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->isLocal()) {
133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      updateAddend(pReloc, pInputSym, pLinker.getLayout());
134affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return;
136affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
137affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // that a .got section is needed.
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (rsym == m_pGOTSymbol->resolveInfo()) {
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      createGOT(pLinker, pOutput);
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
146affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Skip relocation against _gp_disp
147affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (strcmp("_gp_disp", pInputSym.name()) == 0)
148affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return;
149affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
150affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // We test isLocal or if pInputSym is not a dynamic symbol
151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Don't put undef symbols into local entries.
153affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if ((rsym->isLocal() || !isDynamicSymbol(pInputSym, pOutput) ||
154affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      !rsym->isDyn()) && !rsym->isUndef())
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint32_t MipsGNULDBackend::machine() const
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return llvm::ELF::EM_MIPS;
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint8_t MipsGNULDBackend::OSABI() const
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return llvm::ELF::ELFOSABI_NONE;
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint8_t MipsGNULDBackend::ABIVersion() const
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0;
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t MipsGNULDBackend::flags() const
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // TODO: (simon) The correct flag's set depend on command line
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // arguments and flags from input .o files.
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return llvm::ELF::EF_MIPS_ARCH_32R2 |
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         llvm::ELF::EF_MIPS_NOREORDER |
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         llvm::ELF::EF_MIPS_PIC |
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         llvm::ELF::EF_MIPS_CPIC |
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao         E_MIPS_ABI_O32;
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool MipsGNULDBackend::isLittleEndian() const
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Now we support little endian (mipsel) target only.
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaounsigned int MipsGNULDBackend::bitclass() const
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 32;
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
197affc150dc44fab1911775a49636d0ce85333b634Zonr Changuint64_t MipsGNULDBackend::defaultTextSegmentAddr() const
198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
199affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return 0x80000;
200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
201affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
202cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaouint64_t MipsGNULDBackend::abiPageSize(const MCLDInfo& pInfo) const
203cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
204cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (pInfo.options().maxPageSize() > 0)
205cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return pInfo.options().maxPageSize();
206cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  else
207cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return static_cast<uint64_t>(0x10000);
208cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
209cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::doPreLayout(const Output& pOutput,
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pInfo,
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   MCLinker& pLinker)
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // when building shared object, the .got section is must.
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pOutput.type() == Output::DynObj && NULL == m_pGOT) {
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      createGOT(pLinker, pOutput);
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::doPostLayout(const Output& pOutput,
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    const MCLDInfo& pInfo,
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    MCLinker& pLinker)
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsELFDynamic& MipsGNULDBackend::dynamic()
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL == m_pDynamic)
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pDynamic = new MipsELFDynamic(*this);
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst MipsELFDynamic& MipsGNULDBackend::dynamic() const
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert( NULL != m_pDynamic);
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t MipsGNULDBackend::emitSectionData(const Output& pOutput,
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           const LDSection& pSection,
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           const MCLDInfo& pInfo,
247affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                           const Layout& pLayout,
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           MemoryRegion& pRegion) const
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pRegion.size() && "Size of MemoryRegion is zero!");
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
252affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const ELFFileFormat* file_format = getOutputFormat(pOutput);
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (&pSection == &(file_format->getGOT())) {
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint64_t result = m_pGOT->emit(pRegion);
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return result;
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
260affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  fatal(diag::unrecognized_output_sectoin)
261affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          << pSection.name()
262affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          << "mclinker@googlegroups.com";
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0;
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
265affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// isGlobalGOTSymbol - return true if the symbol is the global GOT entry.
266affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool MipsGNULDBackend::isGlobalGOTSymbol(const LDSymbol& pSymbol) const
2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
268affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return std::find(m_GlobalGOTSyms.begin(),
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   m_GlobalGOTSyms.end(), &pSymbol) != m_GlobalGOTSyms.end();
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// emitDynamicSymbol - emit dynamic symbol.
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         Output& pOutput,
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         LDSymbol& pSymbol,
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         const Layout& pLayout,
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         char* strtab,
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         size_t strtabsize,
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         size_t symtabIdx)
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // maintain output's symbol and index map
2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool sym_exist = false;
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  HashTableType::entry_type* entry = 0;
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  entry = m_pSymIndexMap->insert(&pSymbol, sym_exist);
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  entry->setValue(symtabIdx);
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // FIXME: check the endian between host and target
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // write out symbol
2895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  sym32.st_name  = strtabsize;
2905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  sym32.st_value = pSymbol.value();
2915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  sym32.st_size  = getSymbolSize(pSymbol);
2925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  sym32.st_info  = getSymbolInfo(pSymbol);
2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  sym32.st_other = pSymbol.visibility();
2945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  sym32.st_shndx = getSymbolShndx(pSymbol, pLayout);
2955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // write out string
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  strcpy((strtab + strtabsize), pSymbol.name());
2975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao///
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// the size of these tables should be computed before layout
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// layout should computes the start offset of these tables
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::emitDynNamePools(Output& pOutput,
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                        SymbolCategory& pSymbols,
3055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                        const Layout& pLayout,
3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                        const MCLDInfo& pLDInfo)
3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pOutput.hasMemArea());
3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ELFFileFormat* file_format = getOutputFormat(pOutput);
3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection& symtab_sect = file_format->getDynSymTab();
3125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection& strtab_sect = file_format->getDynStrTab();
3135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection& hash_sect   = file_format->getHashTab();
3145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection& dyn_sect    = file_format->getDynamic();
3155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
3175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                           symtab_sect.size());
3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                           strtab_sect.size());
3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MemoryRegion* hash_region = pOutput.memArea()->request(hash_sect.offset(),
3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                         hash_sect.size());
3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  MemoryRegion* dyn_region = pOutput.memArea()->request(dyn_sect.offset(),
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                        dyn_sect.size());
3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // set up symtab_region
3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  llvm::ELF::Elf32_Sym* symtab32 = NULL;
3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symtab32[0].st_name  = 0;
3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symtab32[0].st_value = 0;
3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symtab32[0].st_size  = 0;
3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symtab32[0].st_info  = 0;
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symtab32[0].st_other = 0;
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symtab32[0].st_shndx = 0;
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // set up strtab_region
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  char* strtab = (char*)strtab_region->start();
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  strtab[0] = '\0';
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool sym_exist = false;
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  HashTableType::entry_type* entry = 0;
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // add index 0 symbol into SymIndexMap
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  entry = m_pSymIndexMap->insert(NULL, sym_exist);
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  entry->setValue(0);
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t symtabIdx = 1;
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t strtabsize = 1;
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // emit of .dynsym, and .dynstr except GOT entries
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (SymbolCategory::iterator symbol = pSymbols.begin(),
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       sym_end = pSymbols.end(); symbol != sym_end; ++symbol) {
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (!isDynamicSymbol(**symbol, pOutput))
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      continue;
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
355affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (isGlobalGOTSymbol(**symbol))
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      continue;
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                      strtabsize, symtabIdx);
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // sum up counters
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++symtabIdx;
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    strtabsize += (*symbol)->nameSize() + 1;
3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // emit global GOT
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (std::vector<LDSymbol*>::const_iterator symbol = m_GlobalGOTSyms.begin(),
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       symbol_end = m_GlobalGOTSyms.end();
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao       symbol != symbol_end; ++symbol) {
3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
371affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // Make sure this golbal GOT entry is a dynamic symbol.
372affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // If not, something is wrong earlier when putting this symbol into
373affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    //  global GOT.
374affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (!isDynamicSymbol(**symbol, pOutput))
375affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      fatal(diag::mips_got_symbol) << (*symbol)->name();
376affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                      strtabsize, symtabIdx);
3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // sum up counters
3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++symtabIdx;
3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    strtabsize += (*symbol)->nameSize() + 1;
3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // emit DT_NEED
3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // add DT_NEED strings into .dynstr
3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Rules:
3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //   1. ignore --no-add-needed
3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //   2. force count in --no-as-needed
3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //   3. judge --as-needed
3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ELFDynamic::iterator dt_need = dynamic().needBegin();
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (Input::DynObj == (*input)->type()) {
3955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // --add-needed
3965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if ((*input)->attribute()->isAddNeeded()) {
3975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // --no-as-needed
3985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        if (!(*input)->attribute()->isAsNeeded()) {
3995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          strcpy((strtab + strtabsize), (*input)->name().c_str());
4005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
4015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          strtabsize += (*input)->name().size() + 1;
4025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          ++dt_need;
4035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
4045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // --as-needed
4055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        else if ((*input)->isNeeded()) {
4065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          strcpy((strtab + strtabsize), (*input)->name().c_str());
4075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
4085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          strtabsize += (*input)->name().size() + 1;
4095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          ++dt_need;
4105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        }
4115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
4125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
4135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  } // for
4145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // emit soname
4165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // initialize value of ELF .dynamic section
417affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (Output::DynObj == pOutput.type())
418affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dynamic().applySoname(strtabsize);
4195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  dynamic().applyEntries(pLDInfo, *file_format);
4205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  dynamic().emit(dyn_sect, *dyn_region);
4215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  strcpy((strtab + strtabsize), pOutput.name().c_str());
4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  strtabsize += pOutput.name().size() + 1;
4245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // emit hash table
4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // FIXME: this verion only emit SVR4 hash section.
4275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //        Please add GNU new hash section
4285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // both 32 and 64 bits hash table use 32-bit entry
4305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // set up hash_region
4315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t* word_array = (uint32_t*)hash_region->start();
4325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t& nbucket = word_array[0];
4335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t& nchain  = word_array[1];
4345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  nbucket = getHashBucketCount(symtabIdx, false);
4365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  nchain  = symtabIdx;
4375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t* bucket = (word_array + 2);
4395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t* chain  = (bucket + nbucket);
4405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // initialize bucket
4425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bzero((void*)bucket, nbucket);
4435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  StringHash<ELF> hash_func;
4455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) {
4475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    llvm::StringRef name(strtab + symtab32[sym_idx].st_name);
4485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    size_t bucket_pos = hash_func(name) % nbucket;
4495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    chain[sym_idx] = bucket[bucket_pos];
4505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    bucket[bucket_pos] = sym_idx;
4515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
4525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsGOT& MipsGNULDBackend::getGOT()
4565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pGOT);
4585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
4595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst MipsGOT& MipsGNULDBackend::getGOT() const
4625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pGOT);
4645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
4655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoOutputRelocSection& MipsGNULDBackend::getRelDyn()
4685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pRelDyn);
4705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelDyn;
4715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst OutputRelocSection& MipsGNULDBackend::getRelDyn() const
4745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pRelDyn);
4765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelDyn;
4775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaounsigned int
4805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsGNULDBackend::getTargetSectionOrder(const Output& pOutput,
481affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                        const LDSection& pSectHdr,
482affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                        const MCLDInfo& pInfo) const
4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
484affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const ELFFileFormat* file_format = getOutputFormat(pOutput);
4855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (&pSectHdr == &file_format->getGOT())
4875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return SHO_DATA;
4885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return SHO_UNDEFINED;
4905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// finalizeSymbol - finalize the symbol value
493affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool MipsGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
4945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
495cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (NULL != m_pGpDispSymbol)
496cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
497affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
4985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// allocateCommonSymbols - allocate common symbols in the corresponding
5015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// sections.
5025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// @refer Google gold linker: common.cc: 214
5035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// FIXME: Mips needs to allocate small common symbol
5045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool
5055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMipsGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
5065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
5075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
5085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
5105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return true;
5115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
512affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  SymbolCategory::iterator com_sym, com_end;
5135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // FIXME: If the order of common symbols is defined, then sort common symbols
5155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // std::sort(com_sym, com_end, some kind of order);
5165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // get or create corresponding BSS LDSection
518affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  LDSection* bss_sect = &pLinker.getOrCreateOutputSectHdr(".bss",
5195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   LDFileFormat::BSS,
5205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   llvm::ELF::SHT_NOBITS,
5215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
522affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
523affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  LDSection* tbss_sect = &pLinker.getOrCreateOutputSectHdr(
524affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   ".tbss",
5255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   LDFileFormat::BSS,
5265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   llvm::ELF::SHT_NOBITS,
5275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
528affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
529affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // FIXME: .sbss amd .lbss currently unused.
530affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  /*
531affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  LDSection* sbss_sect = &pLinker.getOrCreateOutputSectHdr(
532affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   ".sbss",
533affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   LDFileFormat::BSS,
534affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   llvm::ELF::SHT_NOBITS,
535affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC |
536affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   llvm::ELF::SHF_MIPS_GPREL);
537affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
538affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  LDSection* lbss_sect = &pLinker.getOrCreateOutputSectHdr(
539affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   ".lbss",
540affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   LDFileFormat::BSS,
541affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   llvm::ELF::SHT_NOBITS,
542affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC |
543affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   llvm::ELF::SHF_MIPS_LOCAL);
544affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  */
545affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
546affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != bss_sect && NULL != tbss_sect);
5475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
548cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // get or create corresponding BSS SectionData
549cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  SectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
550cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  SectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
5515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
552affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // remember original BSS size
553affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint64_t bss_offset  = bss_sect->size();
554affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint64_t tbss_offset = tbss_sect->size();
5555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // allocate all local common symbols
5575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  com_end = symbol_list.localEnd();
558affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
5595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
5605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (ResolveInfo::Common == (*com_sym)->desc()) {
5615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // We have to reset the description of the symbol here. When doing
5625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // incremental linking, the output relocatable object may have common
5635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // symbols. Therefore, we can not treat common symbols as normal symbols
5645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // when emitting the regular name pools. We must change the symbols'
5655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // description here.
5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
567cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
568cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
569affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
570affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
571affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // allocate TLS common symbol in tbss section
572affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        tbss_offset += pLinker.getLayout().appendFragment(*frag,
573affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                          tbss_sect_data,
574affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                          (*com_sym)->value());
575affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
576affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // FIXME: how to identify small and large common symbols?
577affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      else {
578affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        bss_offset += pLinker.getLayout().appendFragment(*frag,
579affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                         bss_sect_data,
580affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                         (*com_sym)->value());
581affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
5825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
5835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // allocate all global common symbols
5865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  com_end = symbol_list.commonEnd();
5875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
5885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // We have to reset the description of the symbol here. When doing
5895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // incremental linking, the output relocatable object may have common
5905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // symbols. Therefore, we can not treat common symbols as normal symbols
5915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // when emitting the regular name pools. We must change the symbols'
5925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // description here.
5935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
594cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
595cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
596affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
597affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
598affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // allocate TLS common symbol in tbss section
599affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      tbss_offset += pLinker.getLayout().appendFragment(*frag,
600affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                        tbss_sect_data,
601affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                        (*com_sym)->value());
602affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
603affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // FIXME: how to identify small and large common symbols?
604affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    else {
605affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      bss_offset += pLinker.getLayout().appendFragment(*frag,
606affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                       bss_sect_data,
607affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                       (*com_sym)->value());
608affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
6095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
611affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  bss_sect->setSize(bss_offset);
612affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  tbss_sect->setSize(tbss_offset);
6135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symbol_list.changeCommonsToGlobal();
6145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
6155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::updateAddend(Relocation& pReloc,
6185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const LDSymbol& pInputSym,
6195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const Layout& pLayout) const
6205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Update value keep in addend if we meet a section symbol
622affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
6235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.setAddend(pLayout.getOutputOffset(
6245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     *pInputSym.fragRef()) + pReloc.addend());
6255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::scanLocalReloc(Relocation& pReloc,
6295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const LDSymbol& pInputSym,
6305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      MCLinker& pLinker,
6315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
6325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const Output& pOutput)
6335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
6355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  updateAddend(pReloc, pInputSym, pLinker.getLayout());
6375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  switch (pReloc.type()){
6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_NONE:
6405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_16:
6415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_32:
6435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if (Output::DynObj == pOutput.type()) {
6445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // TODO: (simon) The gold linker does not create an entry in .rel.dyn
6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // section if the symbol section flags contains SHF_EXECINSTR.
6465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // 1. Find the reason of this condition.
6475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // 2. Check this condition here.
6485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        if (NULL == m_pRelDyn)
6495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          createRelDyn(pLinker, pOutput);
6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_pRelDyn->reserveEntry(*m_pRelocFactory);
6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rsym->setReserved(rsym->reserved() | ReserveRel);
653affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
654affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // Remeber this rsym is a local GOT entry (as if it needs an entry).
655affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // Actually we don't allocate an GOT entry.
656affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        if (NULL == m_pGOT)
657affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          createGOT(pLinker, pOutput);
658affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_pGOT->setLocal(rsym);
6595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
6605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
6615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_REL32:
6625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_26:
6635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_HI16:
6645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_LO16:
6655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_PC16:
6665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_SHIFT5:
6675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_SHIFT6:
6685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_64:
6695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_PAGE:
6705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_OFST:
6715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_SUB:
6725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_INSERT_A:
6735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_INSERT_B:
6745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_DELETE:
6755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_HIGHER:
6765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_HIGHEST:
6775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_SCN_DISP:
6785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_REL16:
6795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
6805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_PJUMP:
6815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_RELGOT:
6825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_JALR:
6835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GLOB_DAT:
6845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_COPY:
6855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_JUMP_SLOT:
6865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
6875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT16:
6885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_CALL16:
6895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if (NULL == m_pGOT)
6905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        createGOT(pLinker, pOutput);
6915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
692affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // For got16 section based relocations, we need to reserve got entries.
693affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (rsym->type() == ResolveInfo::Section) {
694affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_pGOT->reserveLocalEntry();
695affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // Remeber this rsym is a local GOT entry
696affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_pGOT->setLocal(rsym);
697affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        return;
698affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
699affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
7005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
7015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_pGOT->reserveLocalEntry();
7025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rsym->setReserved(rsym->reserved() | ReserveGot);
703affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // Remeber this rsym is a local GOT entry
704affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_pGOT->setLocal(rsym);
7055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
7065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
7075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GPREL32:
7085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GPREL16:
7095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_LITERAL:
7105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
7115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_DISP:
7125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_HI16:
7135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_CALL_HI16:
7145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_LO16:
7155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_CALL_LO16:
7165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
7175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPMOD32:
7185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPREL32:
7195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
7205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPREL64:
7215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_GD:
7225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_LDM:
7235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
7245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
7255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
7265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_TPREL32:
7275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_TPREL64:
7285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
7295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
7305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
7315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    default:
732affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      fatal(diag::unknown_relocation) << (int)pReloc.type()
733affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                      << pReloc.symInfo()->name();
7345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
7355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::scanGlobalReloc(Relocation& pReloc,
7385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       const LDSymbol& pInputSym,
7395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       MCLinker& pLinker,
7405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       const MCLDInfo& pLDInfo,
7415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       const Output& pOutput)
7425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
7435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
7445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  switch (pReloc.type()){
7465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_NONE:
7475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_INSERT_A:
7485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_INSERT_B:
7495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_DELETE:
7505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
7515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPREL64:
7525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_REL16:
7535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
7545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_PJUMP:
7555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_RELGOT:
7565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_TPREL64:
7575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
7585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_32:
7595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_64:
7605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_HI16:
7615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_LO16:
762affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (symbolNeedsDynRel(*rsym, false, pLDInfo, pOutput, true)) {
7635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        if (NULL == m_pRelDyn)
7645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          createRelDyn(pLinker, pOutput);
7655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_pRelDyn->reserveEntry(*m_pRelocFactory);
7675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rsym->setReserved(rsym->reserved() | ReserveRel);
768affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
769affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // Remeber this rsym is a global GOT entry (as if it needs an entry).
770affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // Actually we don't allocate an GOT entry.
771affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        if (NULL == m_pGOT)
772affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          createGOT(pLinker, pOutput);
773affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_pGOT->setGlobal(rsym);
7745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
7755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
7765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT16:
7775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_CALL16:
7785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_DISP:
7795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_HI16:
7805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_CALL_HI16:
7815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_LO16:
7825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_CALL_LO16:
7835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_PAGE:
7845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GOT_OFST:
7855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if (NULL == m_pGOT)
7865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        createGOT(pLinker, pOutput);
7875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
7895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_pGOT->reserveGlobalEntry();
7905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rsym->setReserved(rsym->reserved() | ReserveGot);
7915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        m_GlobalGOTSyms.push_back(rsym->outSymbol());
792affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // Remeber this rsym is a global GOT entry
793affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_pGOT->setGlobal(rsym);
7945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
7955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
7965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_LITERAL:
7975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GPREL32:
798affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      fatal(diag::invalid_global_relocation) << (int)pReloc.type()
799affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                             << pReloc.symInfo()->name();
8005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
8015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GPREL16:
8025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
8035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_26:
8045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_PC16:
8055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
8065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_16:
8075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_SHIFT5:
8085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_SHIFT6:
8095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_SUB:
8105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_HIGHER:
8115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_HIGHEST:
8125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_SCN_DISP:
8135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
8145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPREL32:
8155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_GD:
8165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_LDM:
8175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
8185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
8195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
8205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_TPREL32:
8215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
8225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
8235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
8245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_REL32:
8255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
8265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_JALR:
8275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
8285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_COPY:
8295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_GLOB_DAT:
8305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    case llvm::ELF::R_MIPS_JUMP_SLOT:
831affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      fatal(diag::dynamic_relocation) << (int)pReloc.type();
8325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      break;
8335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    default:
834affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      fatal(diag::unknown_relocation) << (int)pReloc.type()
835affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                      << pReloc.symInfo()->name();
8365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::createGOT(MCLinker& pLinker, const Output& pOutput)
8405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ELFFileFormat* file_format = getOutputFormat(pOutput);
8425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection& got = file_format->getGOT();
8445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_pGOT = new MipsGOT(got, pLinker.getOrCreateSectData(got));
8455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
847affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if ( m_pGOTSymbol != NULL ) {
8485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
8495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     "_GLOBAL_OFFSET_TABLE_",
8505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     false,
8515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Object,
8525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Define,
8535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Local,
8545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     0x0, // size
8555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     0x0, // value
8565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
8575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Hidden);
8585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else {
8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
8615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     "_GLOBAL_OFFSET_TABLE_",
8625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     false,
8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Object,
8645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Define,
8655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Local,
8665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     0x0, // size
8675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     0x0, // value
8685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
8695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                     ResolveInfo::Hidden);
8705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid MipsGNULDBackend::createRelDyn(MCLinker& pLinker, const Output& pOutput)
8745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ELFFileFormat* file_format = getOutputFormat(pOutput);
8765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
877cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // get .rel.dyn LDSection and create SectionData
8785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection& reldyn = file_format->getRelDyn();
879cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // create SectionData and ARMRelDynSection
8805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_pRelDyn = new OutputRelocSection(reldyn,
8815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     pLinker.getOrCreateSectData(reldyn),
8825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                     8);
8835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
8865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
8875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao///
8885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic TargetLDBackend* createMipsLDBackend(const llvm::Target& pTarget,
8895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                            const std::string& pTriple)
8905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  llvm::Triple theTriple(pTriple);
8925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (theTriple.isOSDarwin()) {
8935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "MachO linker is not supported yet");
8945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (theTriple.isOSWindows()) {
8965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "COFF linker is not supported yet");
8975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return new MipsGNULDBackend();
8995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // namespace of mcld
9025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=============================
9045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Force static initialization.
9055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoextern "C" void LLVMInitializeMipsLDBackend() {
9065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Register the linker backend
9075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
9085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                mcld::createMipsLDBackend);
9095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
910