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