15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- X86LDBackend.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#include "X86.h"
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86ELFDynamic.h"
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86LDBackend.h"
12d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "X86Relocator.h"
13d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "X86GNUInfo.h"
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/FillFragment.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/RegionFragment.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h"
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/TargetRegistry.h"
2337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
2487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/ADT/StringRef.h>
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Triple.h>
26cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h>
2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/Support/Dwarf.h>
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstring>
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// X86GNULDBackend
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig,
37551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                 GNUInfo* pInfo,
38551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                 Relocation::Type pCopyRel)
3937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : GNULDBackend(pConfig, pInfo),
4037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelocator(NULL),
4137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pPLT(NULL),
4237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelDyn(NULL),
4337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelPLT(NULL),
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pDynamic(NULL),
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOTSymbol(NULL),
4637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_CopyRel(pCopyRel) {
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::Triple::ArchType arch = pConfig.targets().triple().getArch();
4837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64);
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (arch == llvm::Triple::x86 ||
5087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pConfig.targets().triple().getEnvironment() == llvm::Triple::GNUX32) {
516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_RelEntrySize = 8;
526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_RelaEntrySize = 12;
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (arch == llvm::Triple::x86)
546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PointerRel = llvm::ELF::R_386_32;
556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else
566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_PointerRel = llvm::ELF::R_X86_64_32;
5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_RelEntrySize = 16;
596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_RelaEntrySize = 24;
606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_PointerRel = llvm::ELF::R_X86_64_64;
616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6437b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86GNULDBackend::~X86GNULDBackend() {
65d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  delete m_pRelocator;
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pPLT;
6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pRelDyn;
6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pRelPLT;
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pDynamic;
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst Relocator* X86GNULDBackend::getRelocator() const {
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelocator != NULL);
740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  return m_pRelocator;
750dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
760dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
7737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator* X86GNULDBackend::getRelocator() {
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelocator != NULL);
79d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return m_pRelocator;
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86GNULDBackend::doPreLayout(IRBuilder& pBuilder) {
836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // initialize .dynamic data
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (!config().isCodeStatic() && m_pDynamic == NULL)
856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pDynamic = new X86ELFDynamic(*this, config());
866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // set .got.plt and .got sizes
8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // when building shared object, the .got section is must
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Object != config().codeGenType()) {
906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    setGOTSectionSize(pBuilder);
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set .plt size
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (m_pPLT->hasPLT1())
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_pPLT->finalizeSectionSize();
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // set .rel.dyn/.rela.dyn size
976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!m_pRelDyn->empty()) {
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines          !config().isCodeStatic() &&
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines          "static linkage should not result in a dynamic relocation section");
1016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      setRelDynSize();
1026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
1036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // set .rel.plt/.rela.plt size
1046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!m_pRelPLT->empty()) {
10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(
10637b74a387bb3993387029859c2d9d051c41c724eStephen Hines          !config().isCodeStatic() &&
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          "static linkage should not result in a dynamic relocation section");
1086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      setRelPLTSize();
1096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
110affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (config().options().genUnwindInfo())
11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    addEhFrameForPLT(pBuilder.getModule());
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86GNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) {
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
12137b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86ELFDynamic& X86GNULDBackend::dynamic() {
12237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pDynamic != NULL);
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst X86ELFDynamic& X86GNULDBackend::dynamic() const {
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pDynamic != NULL);
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder, Fragment& pFrag) {
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // define symbol _GLOBAL_OFFSET_TABLE_
135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (m_pGOTSymbol != NULL) {
1366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
13737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "_GLOBAL_OFFSET_TABLE_",
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
14037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
14237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(pFrag, 0x0),
14437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Hidden);
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
1466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "_GLOBAL_OFFSET_TABLE_",
14837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
15137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(pFrag, 0x0),
15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Hidden);
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                          MemoryRegion& pRegion) const {
1606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(pRegion.size() && "Size of MemoryRegion is zero!");
1616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const ELFFileFormat* FileFormat = getOutputFormat();
1636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(FileFormat &&
1646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines         "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
1656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int EntrySize = 0;
1676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t RegionSize = 0;
1686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (FileFormat->hasPLT() && (&pSection == &(FileFormat->getPLT()))) {
17087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    unsigned char* buffer = pRegion.begin();
1716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pPLT->applyPLT0();
1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pPLT->applyPLT1();
1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86PLT::iterator it = m_pPLT->begin();
1756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size();
1766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size);
1786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    RegionSize += plt0_size;
1796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ++it;
1806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLTEntryBase* plt1 = 0;
1826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86PLT::iterator ie = m_pPLT->end();
1836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    while (it != ie) {
1846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      plt1 = &(llvm::cast<PLTEntryBase>(*it));
1856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      EntrySize = plt1->size();
1866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      memcpy(buffer + RegionSize, plt1->getValue(), EntrySize);
1876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      RegionSize += EntrySize;
1886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ++it;
1896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
19037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else if (FileFormat->hasGOT() && (&pSection == &(FileFormat->getGOT()))) {
1916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    RegionSize += emitGOTSectionData(pRegion);
19237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else if (FileFormat->hasGOTPLT() &&
19337b74a387bb3993387029859c2d9d051c41c724eStephen Hines             (&pSection == &(FileFormat->getGOTPLT()))) {
1946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    RegionSize += emitGOTPLTSectionData(pRegion, FileFormat);
19537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
19637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    fatal(diag::unrecognized_output_sectoin) << pSection.name()
19737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                             << "mclinker@googlegroups.com";
1986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
1996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return RegionSize;
2006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
20237b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86PLT& X86GNULDBackend::getPLT() {
20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pPLT != NULL && "PLT section not exist");
2046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pPLT;
2056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
20737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst X86PLT& X86GNULDBackend::getPLT() const {
20837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pPLT != NULL && "PLT section not exist");
2096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pPLT;
2106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
21237b74a387bb3993387029859c2d9d051c41c724eStephen HinesOutputRelocSection& X86GNULDBackend::getRelDyn() {
21337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelDyn != NULL && ".rel.dyn/.rela.dyn section not exist");
2146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pRelDyn;
2156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
21737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst OutputRelocSection& X86GNULDBackend::getRelDyn() const {
21837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelDyn != NULL && ".rel.dyn/.rela.dyn section not exist");
2196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pRelDyn;
2206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
22237b74a387bb3993387029859c2d9d051c41c724eStephen HinesOutputRelocSection& X86GNULDBackend::getRelPLT() {
22337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelPLT != NULL && ".rel.plt/.rela.plt section not exist");
2246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pRelPLT;
2256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
22737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst OutputRelocSection& X86GNULDBackend::getRelPLT() const {
22837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelPLT != NULL && ".rel.plt/.rela.plt section not exist");
2296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pRelPLT;
2306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
23237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesunsigned int X86GNULDBackend::getTargetSectionOrder(
23337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const LDSection& pSectHdr) const {
2346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const ELFFileFormat* file_format = getOutputFormat();
2356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
23687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
2376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (config().options().hasNow())
2386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return SHO_RELRO;
2396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return SHO_RELRO_LAST;
2406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
2416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT())) {
2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (config().options().hasNow())
2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return SHO_RELRO;
2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return SHO_NON_RELRO_FIRST;
2466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
2476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
24887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
2496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return SHO_PLT;
2506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return SHO_UNDEFINED;
2526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
25437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86GNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) {
2556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (LinkerConfig::Object != config().codeGenType()) {
2566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
2576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // same name in input
2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTSymbol =
25937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
26037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            "_GLOBAL_OFFSET_TABLE_",
26137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Object,
26237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Define,
26337b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Local,
26437b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,                  // size
26537b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,                  // value
26637b74a387bb3993387029859c2d9d051c41c724eStephen Hines            FragmentRef::Null(),  // FragRef
26737b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Hidden);
2686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
2696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
27137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86GNULDBackend::addEhFrameForPLT(Module& pModule) {
27287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection* plt_sect = pModule.getSection(".plt");
27387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!plt_sect || plt_sect->size() == 0u)
27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
27687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection* eh_sect = pModule.getSection(".eh_frame");
27787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!eh_sect || !eh_sect->hasEhFrame())
27887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
27987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
28087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  EhFrame* eh_frame = eh_sect->getEhFrame();
28187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SectionData::FragmentListType& frag_list =
28287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      eh_frame->getSectionData()->getFragmentList();
28387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef cie_region = createCIERegionForPLT();
28487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef fde_region = createFDERegionForPLT();
28587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  EhFrame::CIE* cie = new EhFrame::GeneratedCIE(cie_region);
28687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  EhFrame::FDE* fde = new EhFrame::GeneratedFDE(fde_region, *cie);
28787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Augmentation data only contains FDE encoding.
28837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint8_t aug_data =
28937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (uint8_t)(llvm::dwarf::DW_EH_PE_pcrel | llvm::dwarf::DW_EH_PE_sdata4);
29087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  cie->setFDEEncode(aug_data);
29187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  cie->setAugmentationData(std::string(1, aug_data));
29287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
29387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  EhFrame::cie_iterator i = eh_frame->cie_begin();
29487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (EhFrame::cie_iterator e = eh_frame->cie_end(); i != e; ++i) {
29587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    EhFrame::CIE& exist_cie = **i;
29687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (exist_cie == *cie) {
29787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Insert the FDE fragment
29887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      SectionData::iterator cur_iter(exist_cie);
29987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      frag_list.insertAfter(cur_iter, fde);
30087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      fde->setCIE(exist_cie);
30187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
30287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Cleanup the CIE we created
30387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      cie->clearFDEs();
30487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      delete cie;
30587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
30687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
30787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
30887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (i == eh_frame->cie_end()) {
30987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Newly insert
31087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    eh_frame->addCIE(*cie);
31187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    eh_frame->addFDE(*fde);
31287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
31387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
31487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
3156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// finalizeSymbol - finalize the symbol value
31637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool X86GNULDBackend::finalizeTargetSymbols() {
3176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
3186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// doCreateProgramHdrs - backend can implement this function to create the
3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// target-dependent segments
32237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86GNULDBackend::doCreateProgramHdrs(Module& pModule) {
3236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // TODO
3246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GNULDBackend::X86_32GNULDBackend(const LinkerConfig& pConfig,
327551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                       GNUInfo* pInfo)
32837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_386_COPY),
32937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOT(NULL),
33037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOTPLT(NULL) {
3316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
33337b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86_32GNULDBackend::~X86_32GNULDBackend() {
3346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  delete m_pGOT;
3356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  delete m_pGOTPLT;
3366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
33837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool X86_32GNULDBackend::initRelocator() {
33937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pRelocator == NULL) {
340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pRelocator = new X86_32Relocator(*this, config());
3416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
3436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32GNULDBackend::initTargetSections(Module& pModule,
34637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                            ObjectBuilder& pBuilder) {
3476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (LinkerConfig::Object != config().codeGenType()) {
3486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ELFFileFormat* file_format = getOutputFormat();
3496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // initialize .got
3506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection& got = file_format->getGOT();
3516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOT = new X86_32GOT(got);
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // initialize .got.plt
3546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection& gotplt = file_format->getGOTPLT();
3556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTPLT = new X86_32GOTPLT(gotplt);
356affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
3576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // initialize .plt
3586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection& plt = file_format->getPLT();
35987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    plt.setAlign(16u);
360551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    m_pPLT = new X86_32PLT(plt, *m_pGOTPLT, config());
36122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // initialize .rel.plt
3636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection& relplt = file_format->getRelPlt();
3646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    relplt.setLink(&plt);
3656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pRelPLT = new OutputRelocSection(pModule, relplt);
3666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // initialize .rel.dyn
3686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection& reldyn = file_format->getRelDyn();
3696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pRelDyn = new OutputRelocSection(pModule, reldyn);
3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
37337b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86_32GOT& X86_32GNULDBackend::getGOT() {
37437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOT != NULL);
3756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pGOT;
3766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
37837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst X86_32GOT& X86_32GNULDBackend::getGOT() const {
37937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOT != NULL);
3806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pGOT;
3816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
38337b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() {
38437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOTPLT != NULL);
3856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pGOTPLT;
3866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
38837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() const {
38937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOTPLT != NULL);
3906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pGOTPLT;
3916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
39337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesllvm::StringRef X86_32GNULDBackend::createCIERegionForPLT() {
39437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  static const uint8_t data[4 + 4 + 16] = {
39537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x14, 0, 0, 0,  // length
39637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0, 0, 0, 0,  // ID
39737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      1,  // version
39837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      'z', 'R', '\0',  // augmentation string
39937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      1,  // code alignment factor
40037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x7c,  // data alignment factor
40137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      8,  // return address column
40237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      1,  // augmentation data size
40337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_EH_PE_pcrel
40437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          | llvm::dwarf::DW_EH_PE_sdata4,  // FDE encoding
40537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_def_cfa, 4, 4,
40637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_offset + 8, 1,
40737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop,
40837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop
40987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  };
41037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return llvm::StringRef((const char*)data, 4 + 4 + 16);
41137b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
41237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
41337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesllvm::StringRef X86_32GNULDBackend::createFDERegionForPLT() {
41437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  static const uint8_t data[4 + 4 + 32] = {
41537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x24, 0, 0, 0,  // length
41637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0, 0, 0, 0,  // offset to CIE
41737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0, 0, 0, 0,  // offset to PLT
41837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0, 0, 0, 0,  // size of PLT
41937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0,  // augmentation data size
42037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_def_cfa_offset, 8,
42137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_advance_loc + 6,
42237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_def_cfa_offset, 12,
42337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_advance_loc + 10,
42437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_def_cfa_expression,
42537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      11,
42637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_breg4, 4,
42737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_breg8, 0,
42837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_lit15,
42937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_and,
43037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_lit11,
43137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_ge,
43237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_lit2,
43337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_shl,
43437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_plus,
43537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop,
43637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop,
43737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop,
43837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop
43987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  };
44037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return llvm::StringRef((const char*)data, 4 + 4 + 32);
44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
44337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_32GNULDBackend::setRelDynSize() {
4446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ELFFileFormat* file_format = getOutputFormat();
44537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  file_format->getRelDyn().setSize(m_pRelDyn->numOfRelocs() *
44637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   getRelEntrySize());
4476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
4485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
44937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_32GNULDBackend::setRelPLTSize() {
4506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ELFFileFormat* file_format = getOutputFormat();
45137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  file_format->getRelPlt().setSize(m_pRelPLT->numOfRelocs() *
45237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   getRelEntrySize());
4536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
4545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
45537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_32GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder) {
4566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // set .got.plt size
45737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (LinkerConfig::DynObj == config().codeGenType() || m_pGOTPLT->hasGOT1() ||
45837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOTSymbol != NULL) {
4596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTPLT->finalizeSectionSize();
4606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin()));
4615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
4625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // set .got size
4646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!m_pGOT->empty())
4656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOT->finalizeSectionSize();
4666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
4675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
46837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t X86_32GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const {
4696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
4705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
47187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
4725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got = 0;
4746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int EntrySize = X86_32GOTEntry::EntrySize;
4756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t RegionSize = 0;
4766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
47737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (X86_32GOT::iterator it = m_pGOT->begin(), ie = m_pGOT->end(); it != ie;
47837b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it, ++buffer) {
4796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    got = &(llvm::cast<X86_32GOTEntry>((*it)));
4806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *buffer = static_cast<uint32_t>(got->getValue());
4816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    RegionSize += EntrySize;
4825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return RegionSize;
4856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
486affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
48737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t X86_32GNULDBackend::emitGOTPLTSectionData(
48837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    MemoryRegion& pRegion,
48937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFFileFormat* FileFormat) const {
4906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!");
4916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
4926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
493affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
4955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got = 0;
4976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int EntrySize = X86_32GOTEntry::EntrySize;
4986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t RegionSize = 0;
4996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
50037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (X86_32GOTPLT::iterator it = m_pGOTPLT->begin(), ie = m_pGOTPLT->end();
50137b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
50237b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it, ++buffer) {
5036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    got = &(llvm::cast<X86_32GOTEntry>((*it)));
5046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *buffer = static_cast<uint32_t>(got->getValue());
5056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    RegionSize += EntrySize;
5066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
5076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return RegionSize;
5096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GNULDBackend::X86_64GNULDBackend(const LinkerConfig& pConfig,
512551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                       GNUInfo* pInfo)
51337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_X86_64_COPY),
51437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOT(NULL),
51537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOTPLT(NULL) {
5166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
51837b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86_64GNULDBackend::~X86_64GNULDBackend() {
5196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  delete m_pGOT;
5206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  delete m_pGOTPLT;
5216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
52337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool X86_64GNULDBackend::initRelocator() {
52437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pRelocator == NULL) {
525f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pRelocator = new X86_64Relocator(*this, config());
526affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
5276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
5285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
52922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
53037b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86_64GOT& X86_64GNULDBackend::getGOT() {
53137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOT != NULL);
5325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
5335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
53537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst X86_64GOT& X86_64GNULDBackend::getGOT() const {
53637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOT != NULL);
5375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
5385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
54037b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() {
54137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOTPLT != NULL);
542affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return *m_pGOTPLT;
543affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
544affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
54537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() const {
54637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOTPLT != NULL);
547affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return *m_pGOTPLT;
548affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
549affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
55037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesllvm::StringRef X86_64GNULDBackend::createCIERegionForPLT() {
55137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  static const uint8_t data[4 + 4 + 16] = {
55237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x14, 0, 0, 0,  // length
55337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0, 0, 0, 0,  // ID
55437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      1,  // CIE version
55537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      'z', 'R', '\0',  // augmentation string
55637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      1,  // code alignment factor
55737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x78,  // data alignment factor
55837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      16,  // return address column
55937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      1,  // augmentation data size
56037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_EH_PE_pcrel
56137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          | llvm::dwarf::DW_EH_PE_sdata4,  // FDE encoding
56237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_def_cfa, 7, 8,
56337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_offset + 16, 1,
56437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop,
56537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop
56687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  };
56737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return llvm::StringRef((const char*)data, 4 + 4 + 16);
56837b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
56937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
57037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesllvm::StringRef X86_64GNULDBackend::createFDERegionForPLT() {
57137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  static const uint8_t data[4 + 4 + 32] = {
57237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x24, 0, 0, 0,  // length
57337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0, 0, 0, 0,  // ID
57437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0, 0, 0, 0,  // offset to PLT
57537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0, 0, 0, 0,  // size of PLT
57637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0,  // augmentation data size
57737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_def_cfa_offset, 16,
57837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_advance_loc + 6,
57937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_def_cfa_offset, 24,
58037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_advance_loc + 10,
58137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_def_cfa_expression,
58237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      11,
58337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_breg7, 8,
58437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_breg16, 0,
58537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_lit15,
58637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_and,
58737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_lit11,
58837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_ge,
58937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_lit3,
59037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_shl,
59137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_OP_plus,
59237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop,
59337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop,
59437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop,
59537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::dwarf::DW_CFA_nop
59687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  };
59737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return llvm::StringRef((const char*)data, 4 + 4 + 32);
59887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
59987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_64GNULDBackend::setRelDynSize() {
6016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ELFFileFormat* file_format = getOutputFormat();
60237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  file_format->getRelaDyn().setSize(m_pRelDyn->numOfRelocs() *
60337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    getRelaEntrySize());
6045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
60637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_64GNULDBackend::setRelPLTSize() {
6076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ELFFileFormat* file_format = getOutputFormat();
60837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  file_format->getRelaPlt().setSize(m_pRelPLT->numOfRelocs() *
60937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    getRelaEntrySize());
6105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64GNULDBackend::initTargetSections(Module& pModule,
61337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                            ObjectBuilder& pBuilder) {
61422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Object != config().codeGenType()) {
61522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ELFFileFormat* file_format = getOutputFormat();
61622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // initialize .got
61722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection& got = file_format->getGOT();
6186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOT = new X86_64GOT(got);
61922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
62022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // initialize .got.plt
62122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection& gotplt = file_format->getGOTPLT();
6226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTPLT = new X86_64GOTPLT(gotplt);
62322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
62422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // initialize .plt
62522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection& plt = file_format->getPLT();
62687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    plt.setAlign(16u);
627551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    m_pPLT = new X86_64PLT(plt, *m_pGOTPLT, config());
62822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // initialize .rela.plt
6306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection& relplt = file_format->getRelaPlt();
63122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    relplt.setLink(&plt);
632d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_pRelPLT = new OutputRelocSection(pModule, relplt);
633d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
6346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // initialize .rela.dyn
6356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection& reldyn = file_format->getRelaDyn();
636d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_pRelDyn = new OutputRelocSection(pModule, reldyn);
63722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
6385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
64037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_64GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder) {
6416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // set .got.plt size
64237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (LinkerConfig::DynObj == config().codeGenType() || m_pGOTPLT->hasGOT1() ||
64337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOTSymbol != NULL) {
6446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTPLT->finalizeSectionSize();
6456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin()));
64622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
6476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // set .got size
6496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!m_pGOT->empty())
6506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOT->finalizeSectionSize();
6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
65337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t X86_64GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const {
6546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
6556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
65687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
6576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GOTEntry* got = 0;
6596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int EntrySize = X86_64GOTEntry::EntrySize;
6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t RegionSize = 0;
6616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
66237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (X86_64GOT::iterator it = m_pGOT->begin(), ie = m_pGOT->end(); it != ie;
66337b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it, ++buffer) {
6646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    got = &(llvm::cast<X86_64GOTEntry>((*it)));
6656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *buffer = static_cast<uint64_t>(got->getValue());
6666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    RegionSize += EntrySize;
6676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
6686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return RegionSize;
6705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
67237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t X86_64GNULDBackend::emitGOTPLTSectionData(
67337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    MemoryRegion& pRegion,
67437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFFileFormat* FileFormat) const {
6756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!");
6766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
6776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
6786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
67987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
6806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GOTEntry* got = 0;
6826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int EntrySize = X86_64GOTEntry::EntrySize;
6836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t RegionSize = 0;
6846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
68537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (X86_64GOTPLT::iterator it = m_pGOTPLT->begin(), ie = m_pGOTPLT->end();
68637b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
68737b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it, ++buffer) {
6886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    got = &(llvm::cast<X86_64GOTEntry>((*it)));
6896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    *buffer = static_cast<uint64_t>(got->getValue());
6906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    RegionSize += EntrySize;
6916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return RegionSize;
6945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
6975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// createX86LDBackend - the help funtion to create corresponding X86LDBackend
6985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao///
69937b74a387bb3993387029859c2d9d051c41c724eStephen HinesTargetLDBackend* createX86LDBackend(const LinkerConfig& pConfig) {
700d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (pConfig.targets().triple().isOSDarwin()) {
7015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "MachO linker is not supported yet");
7025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /**
7035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return new X86MachOLDBackend(createX86MachOArchiveReader,
7045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                               createX86MachOObjectReader,
7055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                               createX86MachOObjectWriter);
7065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    **/
7075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
708d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (pConfig.targets().triple().isOSWindows()) {
7095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "COFF linker is not supported yet");
7105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /**
7115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return new X86COFFLDBackend(createX86COFFArchiveReader,
7125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                               createX86COFFObjectReader,
7135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                               createX86COFFObjectWriter);
7145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    **/
7155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
71687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::Triple::ArchType arch = pConfig.targets().triple().getArch();
71787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (arch == llvm::Triple::x86)
71837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return new X86_32GNULDBackend(
71937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pConfig, new X86_32GNUInfo(pConfig.targets().triple()));
72037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(arch == llvm::Triple::x86_64);
7216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return new X86_64GNULDBackend(pConfig,
722551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                new X86_64GNUInfo(pConfig.targets().triple()));
7235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
72537b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
7265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
72722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
7285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Force static initialization.
72922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
73022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoextern "C" void MCLDInitializeX86LDBackend() {
7315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Register the linker backend
73237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheX86_32Target,
73337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                mcld::createX86LDBackend);
73437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheX86_64Target,
73537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                mcld::createX86LDBackend);
7365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
737