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