1//===- X86LDBackend.cpp ---------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "X86.h"
10#include "X86ELFDynamic.h"
11#include "X86LDBackend.h"
12#include "X86Relocator.h"
13#include "X86GNUInfo.h"
14
15#include <llvm/ADT/StringRef.h>
16#include <llvm/ADT/Triple.h>
17#include <llvm/Support/Casting.h>
18
19#include <mcld/LinkerConfig.h>
20#include <mcld/IRBuilder.h>
21#include <mcld/LD/ELFFileFormat.h>
22#include <mcld/Fragment/FillFragment.h>
23#include <mcld/Fragment/RegionFragment.h>
24#include <mcld/Support/MsgHandling.h>
25#include <mcld/Support/TargetRegistry.h>
26#include <mcld/Object/ObjectBuilder.h>
27#include <llvm/Support/Dwarf.h>
28
29#include <cstring>
30
31using namespace mcld;
32
33//===----------------------------------------------------------------------===//
34// X86GNULDBackend
35//===----------------------------------------------------------------------===//
36X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig,
37                                 GNUInfo* pInfo,
38                                 Relocation::Type pCopyRel)
39  : GNULDBackend(pConfig, pInfo),
40    m_pRelocator(NULL),
41    m_pPLT(NULL),
42    m_pRelDyn(NULL),
43    m_pRelPLT(NULL),
44    m_pDynamic(NULL),
45    m_pGOTSymbol(NULL),
46    m_CopyRel(pCopyRel)
47{
48  llvm::Triple::ArchType arch = pConfig.targets().triple().getArch();
49  assert (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64);
50  if (arch == llvm::Triple::x86 ||
51      pConfig.targets().triple().getEnvironment() == llvm::Triple::GNUX32) {
52    m_RelEntrySize = 8;
53    m_RelaEntrySize = 12;
54    if (arch == llvm::Triple::x86)
55      m_PointerRel = llvm::ELF::R_386_32;
56    else
57      m_PointerRel = llvm::ELF::R_X86_64_32;
58  }
59  else {
60    m_RelEntrySize = 16;
61    m_RelaEntrySize = 24;
62    m_PointerRel = llvm::ELF::R_X86_64_64;
63  }
64}
65
66X86GNULDBackend::~X86GNULDBackend()
67{
68  delete m_pRelocator;
69  delete m_pPLT;
70  delete m_pRelDyn;
71  delete m_pRelPLT;
72  delete m_pDynamic;
73}
74
75const Relocator* X86GNULDBackend::getRelocator() const
76{
77  assert(NULL != m_pRelocator);
78  return m_pRelocator;
79}
80
81Relocator* X86GNULDBackend::getRelocator()
82{
83  assert(NULL != m_pRelocator);
84  return m_pRelocator;
85}
86
87void X86GNULDBackend::doPreLayout(IRBuilder& pBuilder)
88{
89  // initialize .dynamic data
90  if (!config().isCodeStatic() && NULL == m_pDynamic)
91    m_pDynamic = new X86ELFDynamic(*this, config());
92
93  // set .got.plt and .got sizes
94  // when building shared object, the .got section is must
95  if (LinkerConfig::Object != config().codeGenType()) {
96    setGOTSectionSize(pBuilder);
97
98    // set .plt size
99    if (m_pPLT->hasPLT1())
100      m_pPLT->finalizeSectionSize();
101
102    // set .rel.dyn/.rela.dyn size
103    if (!m_pRelDyn->empty()) {
104      assert(!config().isCodeStatic() &&
105            "static linkage should not result in a dynamic relocation section");
106      setRelDynSize();
107    }
108    // set .rel.plt/.rela.plt size
109    if (!m_pRelPLT->empty()) {
110      assert(!config().isCodeStatic() &&
111            "static linkage should not result in a dynamic relocation section");
112      setRelPLTSize();
113    }
114  }
115
116  if (config().options().genUnwindInfo())
117    addEhFrameForPLT(pBuilder.getModule());
118}
119
120void X86GNULDBackend::doPostLayout(Module& pModule,
121                                   IRBuilder& pBuilder)
122{
123}
124
125/// dynamic - the dynamic section of the target machine.
126/// Use co-variant return type to return its own dynamic section.
127X86ELFDynamic& X86GNULDBackend::dynamic()
128{
129  assert(NULL != m_pDynamic);
130  return *m_pDynamic;
131}
132
133/// dynamic - the dynamic section of the target machine.
134/// Use co-variant return type to return its own dynamic section.
135const X86ELFDynamic& X86GNULDBackend::dynamic() const
136{
137  assert(NULL != m_pDynamic);
138  return *m_pDynamic;
139}
140
141void X86GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder, Fragment& pFrag)
142{
143  // define symbol _GLOBAL_OFFSET_TABLE_
144  if (m_pGOTSymbol != NULL) {
145    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
146                     "_GLOBAL_OFFSET_TABLE_",
147                     ResolveInfo::Object,
148                     ResolveInfo::Define,
149                     ResolveInfo::Local,
150                     0x0, // size
151                     0x0, // value
152                     FragmentRef::Create(pFrag, 0x0),
153                     ResolveInfo::Hidden);
154  }
155  else {
156    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
157                     "_GLOBAL_OFFSET_TABLE_",
158                     ResolveInfo::Object,
159                     ResolveInfo::Define,
160                     ResolveInfo::Local,
161                     0x0, // size
162                     0x0, // value
163                     FragmentRef::Create(pFrag, 0x0),
164                     ResolveInfo::Hidden);
165  }
166}
167
168uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
169                                          MemoryRegion& pRegion) const
170{
171  assert(pRegion.size() && "Size of MemoryRegion is zero!");
172
173  const ELFFileFormat* FileFormat = getOutputFormat();
174  assert(FileFormat &&
175         "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
176
177  unsigned int EntrySize = 0;
178  uint64_t RegionSize = 0;
179
180  if (FileFormat->hasPLT() && (&pSection == &(FileFormat->getPLT()))) {
181    unsigned char* buffer = pRegion.begin();
182
183    m_pPLT->applyPLT0();
184    m_pPLT->applyPLT1();
185    X86PLT::iterator it = m_pPLT->begin();
186    unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size();
187
188    memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size);
189    RegionSize += plt0_size;
190    ++it;
191
192    PLTEntryBase* plt1 = 0;
193    X86PLT::iterator ie = m_pPLT->end();
194    while (it != ie) {
195      plt1 = &(llvm::cast<PLTEntryBase>(*it));
196      EntrySize = plt1->size();
197      memcpy(buffer + RegionSize, plt1->getValue(), EntrySize);
198      RegionSize += EntrySize;
199      ++it;
200    }
201  }
202  else if (FileFormat->hasGOT() && (&pSection == &(FileFormat->getGOT()))) {
203    RegionSize += emitGOTSectionData(pRegion);
204  }
205  else if (FileFormat->hasGOTPLT() &&
206           (&pSection == &(FileFormat->getGOTPLT()))) {
207    RegionSize += emitGOTPLTSectionData(pRegion, FileFormat);
208  }
209  else {
210    fatal(diag::unrecognized_output_sectoin)
211            << pSection.name()
212            << "mclinker@googlegroups.com";
213  }
214  return RegionSize;
215}
216
217X86PLT& X86GNULDBackend::getPLT()
218{
219  assert(NULL != m_pPLT && "PLT section not exist");
220  return *m_pPLT;
221}
222
223const X86PLT& X86GNULDBackend::getPLT() const
224{
225  assert(NULL != m_pPLT && "PLT section not exist");
226  return *m_pPLT;
227}
228
229OutputRelocSection& X86GNULDBackend::getRelDyn()
230{
231  assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist");
232  return *m_pRelDyn;
233}
234
235const OutputRelocSection& X86GNULDBackend::getRelDyn() const
236{
237  assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist");
238  return *m_pRelDyn;
239}
240
241OutputRelocSection& X86GNULDBackend::getRelPLT()
242{
243  assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist");
244  return *m_pRelPLT;
245}
246
247const OutputRelocSection& X86GNULDBackend::getRelPLT() const
248{
249  assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist");
250  return *m_pRelPLT;
251}
252
253unsigned int
254X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
255{
256  const ELFFileFormat* file_format = getOutputFormat();
257
258  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
259    if (config().options().hasNow())
260      return SHO_RELRO;
261    return SHO_RELRO_LAST;
262  }
263
264  if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT())) {
265    if (config().options().hasNow())
266      return SHO_RELRO;
267    return SHO_NON_RELRO_FIRST;
268  }
269
270  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
271    return SHO_PLT;
272
273  return SHO_UNDEFINED;
274}
275
276void X86GNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
277{
278  if (LinkerConfig::Object != config().codeGenType()) {
279    // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
280    // same name in input
281    m_pGOTSymbol =
282      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
283                                                "_GLOBAL_OFFSET_TABLE_",
284                                                ResolveInfo::Object,
285                                                ResolveInfo::Define,
286                                                ResolveInfo::Local,
287                                                0x0,  // size
288                                                0x0,  // value
289                                                FragmentRef::Null(), // FragRef
290                                                ResolveInfo::Hidden);
291  }
292}
293
294void X86GNULDBackend::addEhFrameForPLT(Module& pModule)
295{
296  LDSection* plt_sect = pModule.getSection(".plt");
297  if (!plt_sect || plt_sect->size() == 0u)
298    return;
299
300  LDSection* eh_sect = pModule.getSection(".eh_frame");
301  if (!eh_sect || !eh_sect->hasEhFrame())
302    return;
303
304  EhFrame* eh_frame = eh_sect->getEhFrame();
305  SectionData::FragmentListType& frag_list =
306      eh_frame->getSectionData()->getFragmentList();
307  llvm::StringRef cie_region = createCIERegionForPLT();
308  llvm::StringRef fde_region = createFDERegionForPLT();
309  EhFrame::CIE* cie = new EhFrame::GeneratedCIE(cie_region);
310  EhFrame::FDE* fde = new EhFrame::GeneratedFDE(fde_region, *cie);
311  // Augmentation data only contains FDE encoding.
312  uint8_t aug_data = (uint8_t)(llvm::dwarf::DW_EH_PE_pcrel |
313                               llvm::dwarf::DW_EH_PE_sdata4);
314  cie->setFDEEncode(aug_data);
315  cie->setAugmentationData(std::string(1, aug_data));
316
317  EhFrame::cie_iterator i = eh_frame->cie_begin();
318  for (EhFrame::cie_iterator e = eh_frame->cie_end(); i != e; ++i) {
319    EhFrame::CIE& exist_cie = **i;
320    if (exist_cie == *cie) {
321      // Insert the FDE fragment
322      SectionData::iterator cur_iter(exist_cie);
323      frag_list.insertAfter(cur_iter, fde);
324      fde->setCIE(exist_cie);
325
326      // Cleanup the CIE we created
327      cie->clearFDEs();
328      delete cie;
329      break;
330    }
331  }
332  if (i == eh_frame->cie_end()) {
333    // Newly insert
334    eh_frame->addCIE(*cie);
335    eh_frame->addFDE(*fde);
336  }
337}
338
339/// finalizeSymbol - finalize the symbol value
340bool X86GNULDBackend::finalizeTargetSymbols()
341{
342  return true;
343}
344
345/// doCreateProgramHdrs - backend can implement this function to create the
346/// target-dependent segments
347void X86GNULDBackend::doCreateProgramHdrs(Module& pModule)
348{
349  // TODO
350}
351
352X86_32GNULDBackend::X86_32GNULDBackend(const LinkerConfig& pConfig,
353                                       GNUInfo* pInfo)
354  : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_386_COPY),
355    m_pGOT (NULL),
356    m_pGOTPLT (NULL) {
357}
358
359X86_32GNULDBackend::~X86_32GNULDBackend()
360{
361  delete m_pGOT;
362  delete m_pGOTPLT;
363}
364
365bool X86_32GNULDBackend::initRelocator()
366{
367  if (NULL == m_pRelocator) {
368    m_pRelocator = new X86_32Relocator(*this, config());
369  }
370  return true;
371}
372
373void X86_32GNULDBackend::initTargetSections(Module& pModule,
374                                            ObjectBuilder& pBuilder)
375{
376  if (LinkerConfig::Object != config().codeGenType()) {
377    ELFFileFormat* file_format = getOutputFormat();
378    // initialize .got
379    LDSection& got = file_format->getGOT();
380    m_pGOT = new X86_32GOT(got);
381
382    // initialize .got.plt
383    LDSection& gotplt = file_format->getGOTPLT();
384    m_pGOTPLT = new X86_32GOTPLT(gotplt);
385
386    // initialize .plt
387    LDSection& plt = file_format->getPLT();
388    plt.setAlign(16u);
389    m_pPLT = new X86_32PLT(plt, *m_pGOTPLT, config());
390
391    // initialize .rel.plt
392    LDSection& relplt = file_format->getRelPlt();
393    relplt.setLink(&plt);
394    m_pRelPLT = new OutputRelocSection(pModule, relplt);
395
396    // initialize .rel.dyn
397    LDSection& reldyn = file_format->getRelDyn();
398    m_pRelDyn = new OutputRelocSection(pModule, reldyn);
399
400  }
401}
402
403X86_32GOT& X86_32GNULDBackend::getGOT()
404{
405  assert(NULL != m_pGOT);
406  return *m_pGOT;
407}
408
409const X86_32GOT& X86_32GNULDBackend::getGOT() const
410{
411  assert(NULL != m_pGOT);
412  return *m_pGOT;
413}
414
415X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT()
416{
417  assert(NULL != m_pGOTPLT);
418  return *m_pGOTPLT;
419}
420
421const X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() const
422{
423  assert(NULL != m_pGOTPLT);
424  return *m_pGOTPLT;
425}
426
427llvm::StringRef X86_32GNULDBackend::createCIERegionForPLT()
428{
429  using namespace llvm::dwarf;
430  static const uint8_t data[4+4+16] = {
431    0x14, 0, 0, 0, // length
432    0, 0, 0, 0, // ID
433    1,  // version
434    'z', 'R', '\0', // augmentation string
435    1,  // code alignment factor
436    0x7c, // data alignment factor
437    8,  // return address column
438    1,  // augmentation data size
439    DW_EH_PE_pcrel | DW_EH_PE_sdata4, // FDE encoding
440    DW_CFA_def_cfa, 4, 4,
441    DW_CFA_offset + 8, 1,
442    DW_CFA_nop,
443    DW_CFA_nop
444  };
445  return llvm::StringRef((const char*)data, 4+4+16);
446}
447
448llvm::StringRef X86_32GNULDBackend::createFDERegionForPLT()
449{
450  using namespace llvm::dwarf;
451  static const uint8_t data[4+4+32] = {
452    0x24, 0, 0, 0,  // length
453    0, 0, 0, 0,   // offset to CIE
454    0, 0, 0, 0,   // offset to PLT
455    0, 0, 0, 0,   // size of PLT
456    0,            // augmentation data size
457    DW_CFA_def_cfa_offset, 8,
458    DW_CFA_advance_loc + 6,
459    DW_CFA_def_cfa_offset, 12,
460    DW_CFA_advance_loc + 10,
461    DW_CFA_def_cfa_expression,
462    11,
463    DW_OP_breg4, 4,
464    DW_OP_breg8, 0,
465    DW_OP_lit15,
466    DW_OP_and,
467    DW_OP_lit11,
468    DW_OP_ge,
469    DW_OP_lit2,
470    DW_OP_shl,
471    DW_OP_plus,
472    DW_CFA_nop,
473    DW_CFA_nop,
474    DW_CFA_nop,
475    DW_CFA_nop
476  };
477  return llvm::StringRef((const char*)data, 4+4+32);
478}
479
480void X86_32GNULDBackend::setRelDynSize()
481{
482  ELFFileFormat* file_format = getOutputFormat();
483  file_format->getRelDyn().setSize
484    (m_pRelDyn->numOfRelocs() * getRelEntrySize());
485}
486
487void X86_32GNULDBackend::setRelPLTSize()
488{
489  ELFFileFormat* file_format = getOutputFormat();
490  file_format->getRelPlt().setSize
491    (m_pRelPLT->numOfRelocs() * getRelEntrySize());
492}
493
494void X86_32GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder)
495{
496  // set .got.plt size
497  if (LinkerConfig::DynObj == config().codeGenType() ||
498      m_pGOTPLT->hasGOT1() ||
499      NULL != m_pGOTSymbol) {
500    m_pGOTPLT->finalizeSectionSize();
501    defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin()));
502  }
503
504  // set .got size
505  if (!m_pGOT->empty())
506    m_pGOT->finalizeSectionSize();
507}
508
509uint64_t X86_32GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const
510{
511  assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
512
513  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
514
515  X86_32GOTEntry* got = 0;
516  unsigned int EntrySize = X86_32GOTEntry::EntrySize;
517  uint64_t RegionSize = 0;
518
519  for (X86_32GOT::iterator it = m_pGOT->begin(),
520       ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
521    got = &(llvm::cast<X86_32GOTEntry>((*it)));
522    *buffer = static_cast<uint32_t>(got->getValue());
523    RegionSize += EntrySize;
524  }
525
526  return RegionSize;
527}
528
529uint64_t X86_32GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion,
530                                                   const ELFFileFormat* FileFormat) const
531{
532  assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!");
533  m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
534  m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
535
536  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
537
538  X86_32GOTEntry* got = 0;
539  unsigned int EntrySize = X86_32GOTEntry::EntrySize;
540  uint64_t RegionSize = 0;
541
542  for (X86_32GOTPLT::iterator it = m_pGOTPLT->begin(),
543       ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
544    got = &(llvm::cast<X86_32GOTEntry>((*it)));
545    *buffer = static_cast<uint32_t>(got->getValue());
546    RegionSize += EntrySize;
547  }
548
549  return RegionSize;
550}
551
552X86_64GNULDBackend::X86_64GNULDBackend(const LinkerConfig& pConfig,
553                                       GNUInfo* pInfo)
554  : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_X86_64_COPY),
555    m_pGOT (NULL),
556    m_pGOTPLT (NULL) {
557}
558
559X86_64GNULDBackend::~X86_64GNULDBackend()
560{
561  delete m_pGOT;
562  delete m_pGOTPLT;
563}
564
565bool X86_64GNULDBackend::initRelocator()
566{
567  if (NULL == m_pRelocator) {
568    m_pRelocator = new X86_64Relocator(*this, config());
569  }
570  return true;
571}
572
573X86_64GOT& X86_64GNULDBackend::getGOT()
574{
575  assert(NULL != m_pGOT);
576  return *m_pGOT;
577}
578
579const X86_64GOT& X86_64GNULDBackend::getGOT() const
580{
581  assert(NULL != m_pGOT);
582  return *m_pGOT;
583}
584
585X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT()
586{
587  assert(NULL != m_pGOTPLT);
588  return *m_pGOTPLT;
589}
590
591const X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() const
592{
593  assert(NULL != m_pGOTPLT);
594  return *m_pGOTPLT;
595}
596
597llvm::StringRef X86_64GNULDBackend::createCIERegionForPLT()
598{
599  using namespace llvm::dwarf;
600  static const uint8_t data[4+4+16] = {
601    0x14, 0, 0, 0,  // length
602    0, 0, 0, 0,   // ID
603    1,          // CIE version
604    'z', 'R', '\0', // augmentation string
605    1,          // code alignment factor
606    0x78,       // data alignment factor
607    16,         // return address column
608    1,          // augmentation data size
609    DW_EH_PE_pcrel | DW_EH_PE_sdata4, // FDE encoding
610    DW_CFA_def_cfa, 7, 8,
611    DW_CFA_offset + 16, 1,
612    DW_CFA_nop,
613    DW_CFA_nop
614  };
615  return llvm::StringRef((const char*)data, 4+4+16);
616}
617
618llvm::StringRef X86_64GNULDBackend::createFDERegionForPLT()
619{
620  using namespace llvm::dwarf;
621  static const uint8_t data[4+4+32] = {
622    0x24, 0, 0, 0,  // length
623    0, 0, 0, 0,   // ID
624    0, 0, 0, 0,   // offset to PLT
625    0, 0, 0, 0,   // size of PLT
626    0,            // augmentation data size
627    DW_CFA_def_cfa_offset, 16,
628    DW_CFA_advance_loc + 6,
629    DW_CFA_def_cfa_offset, 24,
630    DW_CFA_advance_loc + 10,
631    DW_CFA_def_cfa_expression,
632    11,
633    DW_OP_breg7, 8,
634    DW_OP_breg16, 0,
635    DW_OP_lit15,
636    DW_OP_and,
637    DW_OP_lit11,
638    DW_OP_ge,
639    DW_OP_lit3,
640    DW_OP_shl,
641    DW_OP_plus,
642    DW_CFA_nop,
643    DW_CFA_nop,
644    DW_CFA_nop,
645    DW_CFA_nop
646  };
647  return llvm::StringRef((const char*)data, 4+4+32);
648}
649
650void X86_64GNULDBackend::setRelDynSize()
651{
652  ELFFileFormat* file_format = getOutputFormat();
653  file_format->getRelaDyn().setSize
654    (m_pRelDyn->numOfRelocs() * getRelaEntrySize());
655}
656
657void X86_64GNULDBackend::setRelPLTSize()
658{
659  ELFFileFormat* file_format = getOutputFormat();
660  file_format->getRelaPlt().setSize
661    (m_pRelPLT->numOfRelocs() * getRelaEntrySize());
662}
663
664void X86_64GNULDBackend::initTargetSections(Module& pModule,
665                                            ObjectBuilder& pBuilder)
666{
667  if (LinkerConfig::Object != config().codeGenType()) {
668    ELFFileFormat* file_format = getOutputFormat();
669    // initialize .got
670    LDSection& got = file_format->getGOT();
671    m_pGOT = new X86_64GOT(got);
672
673    // initialize .got.plt
674    LDSection& gotplt = file_format->getGOTPLT();
675    m_pGOTPLT = new X86_64GOTPLT(gotplt);
676
677    // initialize .plt
678    LDSection& plt = file_format->getPLT();
679    plt.setAlign(16u);
680    m_pPLT = new X86_64PLT(plt, *m_pGOTPLT, config());
681
682    // initialize .rela.plt
683    LDSection& relplt = file_format->getRelaPlt();
684    relplt.setLink(&plt);
685    m_pRelPLT = new OutputRelocSection(pModule, relplt);
686
687    // initialize .rela.dyn
688    LDSection& reldyn = file_format->getRelaDyn();
689    m_pRelDyn = new OutputRelocSection(pModule, reldyn);
690
691  }
692}
693
694void X86_64GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder)
695{
696  // set .got.plt size
697  if (LinkerConfig::DynObj == config().codeGenType() ||
698      m_pGOTPLT->hasGOT1() ||
699      NULL != m_pGOTSymbol) {
700    m_pGOTPLT->finalizeSectionSize();
701    defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin()));
702  }
703
704  // set .got size
705  if (!m_pGOT->empty())
706    m_pGOT->finalizeSectionSize();
707}
708
709uint64_t X86_64GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const
710{
711  assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
712
713  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
714
715  X86_64GOTEntry* got = 0;
716  unsigned int EntrySize = X86_64GOTEntry::EntrySize;
717  uint64_t RegionSize = 0;
718
719  for (X86_64GOT::iterator it = m_pGOT->begin(),
720       ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
721    got = &(llvm::cast<X86_64GOTEntry>((*it)));
722    *buffer = static_cast<uint64_t>(got->getValue());
723    RegionSize += EntrySize;
724  }
725
726  return RegionSize;
727}
728
729uint64_t
730X86_64GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion,
731                                          const ELFFileFormat* FileFormat) const
732{
733  assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!");
734  m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
735  m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
736
737  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
738
739  X86_64GOTEntry* got = 0;
740  unsigned int EntrySize = X86_64GOTEntry::EntrySize;
741  uint64_t RegionSize = 0;
742
743  for (X86_64GOTPLT::iterator it = m_pGOTPLT->begin(),
744       ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
745    got = &(llvm::cast<X86_64GOTEntry>((*it)));
746    *buffer = static_cast<uint64_t>(got->getValue());
747    RegionSize += EntrySize;
748  }
749
750  return RegionSize;
751}
752
753namespace mcld {
754
755//===----------------------------------------------------------------------===//
756/// createX86LDBackend - the help funtion to create corresponding X86LDBackend
757///
758TargetLDBackend* createX86LDBackend(const LinkerConfig& pConfig)
759{
760  if (pConfig.targets().triple().isOSDarwin()) {
761    assert(0 && "MachO linker is not supported yet");
762    /**
763    return new X86MachOLDBackend(createX86MachOArchiveReader,
764                               createX86MachOObjectReader,
765                               createX86MachOObjectWriter);
766    **/
767  }
768  if (pConfig.targets().triple().isOSWindows()) {
769    assert(0 && "COFF linker is not supported yet");
770    /**
771    return new X86COFFLDBackend(createX86COFFArchiveReader,
772                               createX86COFFObjectReader,
773                               createX86COFFObjectWriter);
774    **/
775  }
776  llvm::Triple::ArchType arch = pConfig.targets().triple().getArch();
777  if (arch == llvm::Triple::x86)
778    return new X86_32GNULDBackend(pConfig,
779                                  new X86_32GNUInfo(pConfig.targets().triple()));
780  assert (arch == llvm::Triple::x86_64);
781  return new X86_64GNULDBackend(pConfig,
782                                new X86_64GNUInfo(pConfig.targets().triple()));
783}
784
785} // namespace of mcld
786
787//===----------------------------------------------------------------------===//
788// Force static initialization.
789//===----------------------------------------------------------------------===//
790extern "C" void MCLDInitializeX86LDBackend() {
791  // Register the linker backend
792  mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_32Target, createX86LDBackend);
793  mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_64Target, createX86LDBackend);
794}
795