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