X86LDBackend.cpp revision cedee4b38f4786845183be7f5916dd520a170ae0
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
10#include "X86.h"
11#include "X86ELFDynamic.h"
12#include "X86LDBackend.h"
13#include "X86RelocationFactory.h"
14
15#include <llvm/ADT/Triple.h>
16#include <llvm/Support/Casting.h>
17
18#include <mcld/LD/SectionMap.h>
19#include <mcld/LD/FillFragment.h>
20#include <mcld/LD/RegionFragment.h>
21#include <mcld/MC/MCLDInfo.h>
22#include <mcld/MC/MCLDOutput.h>
23#include <mcld/MC/MCLinker.h>
24#include <mcld/Support/MemoryRegion.h>
25#include <mcld/Support/MsgHandling.h>
26#include <mcld/Support/TargetRegistry.h>
27
28#include <cstring>
29
30using namespace mcld;
31
32X86GNULDBackend::X86GNULDBackend()
33  : m_pRelocFactory(NULL),
34    m_pGOT(NULL),
35    m_pPLT(NULL),
36    m_pGOTPLT(NULL),
37    m_pRelDyn(NULL),
38    m_pRelPLT(NULL),
39    m_pDynamic(NULL),
40    m_pGOTSymbol(NULL) {
41}
42
43X86GNULDBackend::~X86GNULDBackend()
44{
45  if (NULL != m_pRelocFactory)
46    delete m_pRelocFactory;
47  if (NULL != m_pGOT)
48    delete m_pGOT;
49  if (NULL != m_pPLT)
50    delete m_pPLT;
51  if (NULL != m_pGOTPLT)
52    delete m_pGOTPLT;
53  if (NULL !=m_pRelDyn)
54    delete m_pRelDyn;
55  if (NULL != m_pRelPLT)
56    delete m_pRelPLT;
57  if (NULL != m_pDynamic)
58    delete m_pDynamic;
59}
60
61RelocationFactory* X86GNULDBackend::getRelocFactory()
62{
63  assert(NULL != m_pRelocFactory);
64  return m_pRelocFactory;
65}
66
67bool X86GNULDBackend::initRelocFactory(const MCLinker& pLinker)
68{
69  if (NULL == m_pRelocFactory) {
70    m_pRelocFactory = new X86RelocationFactory(1024, *this);
71    m_pRelocFactory->setLayout(pLinker.getLayout());
72  }
73  return true;
74}
75
76void X86GNULDBackend::doPreLayout(const Output& pOutput,
77                                  const MCLDInfo& pInfo,
78                                  MCLinker& pLinker)
79{
80  // when building shared object, the .got section is needed
81  if (Output::DynObj == pOutput.type() && (NULL == m_pGOTPLT)) {
82    createX86GOTPLT(pLinker, pOutput);
83  }
84}
85
86void X86GNULDBackend::doPostLayout(const Output& pOutput,
87                                   const MCLDInfo& pInfo,
88                                   MCLinker& pLinker)
89{
90}
91
92/// dynamic - the dynamic section of the target machine.
93/// Use co-variant return type to return its own dynamic section.
94X86ELFDynamic& X86GNULDBackend::dynamic()
95{
96  if (NULL == m_pDynamic)
97    m_pDynamic = new X86ELFDynamic(*this);
98
99  return *m_pDynamic;
100}
101
102/// dynamic - the dynamic section of the target machine.
103/// Use co-variant return type to return its own dynamic section.
104const X86ELFDynamic& X86GNULDBackend::dynamic() const
105{
106  assert( NULL != m_pDynamic);
107  return *m_pDynamic;
108}
109
110void X86GNULDBackend::createX86GOT(MCLinker& pLinker, const Output& pOutput)
111{
112  // get .got LDSection and create SectionData
113  ELFFileFormat* file_format = getOutputFormat(pOutput);
114
115  LDSection& got = file_format->getGOT();
116  m_pGOT = new X86GOT(got, pLinker.getOrCreateSectData(got));
117}
118
119void X86GNULDBackend::createX86GOTPLT(MCLinker& pLinker, const Output& pOutput)
120{
121  // get .got.plt LDSection and create SectionData
122  ELFFileFormat* file_format = getOutputFormat(pOutput);
123
124  LDSection& gotplt = file_format->getGOTPLT();
125  m_pGOTPLT = new X86GOTPLT(gotplt, pLinker.getOrCreateSectData(gotplt));
126
127  // define symbol _GLOBAL_OFFSET_TABLE_ when .got.plt create
128  if (m_pGOTSymbol != NULL) {
129    pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
130                     "_GLOBAL_OFFSET_TABLE_",
131                     false,
132                     ResolveInfo::Object,
133                     ResolveInfo::Define,
134                     ResolveInfo::Local,
135                     0x0, // size
136                     0x0, // value
137                     pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
138                                                         0x0),
139                     ResolveInfo::Hidden);
140  }
141  else {
142    m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
143                     "_GLOBAL_OFFSET_TABLE_",
144                     false,
145                     ResolveInfo::Object,
146                     ResolveInfo::Define,
147                     ResolveInfo::Local,
148                     0x0, // size
149                     0x0, // value
150                     pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
151                                                          0x0),
152                     ResolveInfo::Hidden);
153  }
154}
155
156void X86GNULDBackend::createX86PLTandRelPLT(MCLinker& pLinker,
157                                            const Output& pOutput)
158{
159  ELFFileFormat* file_format = getOutputFormat(pOutput);
160
161  LDSection& plt = file_format->getPLT();
162  LDSection& relplt = file_format->getRelPlt();
163  assert(m_pGOTPLT != NULL);
164  // create SectionData and X86PLT
165  m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOTPLT, pOutput);
166
167  // set info of .rel.plt to .plt
168  relplt.setLink(&plt);
169  // create SectionData and X86RelDynSection
170  m_pRelPLT = new OutputRelocSection(relplt,
171                                     pLinker.getOrCreateSectData(relplt),
172                                     8);
173}
174
175void X86GNULDBackend::createX86RelDyn(MCLinker& pLinker,
176                                      const Output& pOutput)
177{
178  // get .rel.dyn LDSection and create SectionData
179  ELFFileFormat* file_format = getOutputFormat(pOutput);
180
181  LDSection& reldyn = file_format->getRelDyn();
182  // create SectionData and X86RelDynSection
183  m_pRelDyn = new OutputRelocSection(reldyn,
184                                     pLinker.getOrCreateSectData(reldyn),
185                                     8);
186}
187
188void X86GNULDBackend::addCopyReloc(ResolveInfo& pSym)
189{
190  bool exist;
191  Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
192  rel_entry.setType(llvm::ELF::R_386_COPY);
193  assert(pSym.outSymbol()->hasFragRef());
194  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
195  rel_entry.setSymInfo(&pSym);
196}
197
198LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(MCLinker& pLinker,
199                                                    const ResolveInfo& pSym)
200{
201  // For a symbol needing copy relocation, define a copy symbol in the BSS
202  // section and all other reference to this symbol should refer to this
203  // copy.
204
205  // get or create corresponding BSS LDSection
206  LDSection* bss_sect_hdr = NULL;
207  if (ResolveInfo::ThreadLocal == pSym.type()) {
208    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
209                                   ".tbss",
210                                   LDFileFormat::BSS,
211                                   llvm::ELF::SHT_NOBITS,
212                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
213  }
214  else {
215    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
216                                   LDFileFormat::BSS,
217                                   llvm::ELF::SHT_NOBITS,
218                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
219  }
220
221  // get or create corresponding BSS SectionData
222  assert(NULL != bss_sect_hdr);
223  SectionData& bss_section = pLinker.getOrCreateSectData(
224                                     *bss_sect_hdr);
225
226  // Determine the alignment by the symbol value
227  // FIXME: here we use the largest alignment
228  uint32_t addralign = bitclass() / 8;
229
230  // allocate space in BSS for the copy symbol
231  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
232  uint64_t size = pLinker.getLayout().appendFragment(*frag,
233                                                     bss_section,
234                                                     addralign);
235  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
236
237  // change symbol binding to Global if it's a weak symbol
238  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
239  if (binding == ResolveInfo::Weak)
240    binding = ResolveInfo::Global;
241
242  // Define the copy symbol in the bss section and resolve it
243  LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
244                      pSym.name(),
245                      false,
246                      (ResolveInfo::Type)pSym.type(),
247                      ResolveInfo::Define,
248                      binding,
249                      pSym.size(),  // size
250                      0x0,          // value
251                      pLinker.getLayout().getFragmentRef(*frag, 0x0),
252                      (ResolveInfo::Visibility)pSym.other());
253
254  return *cpy_sym;
255}
256
257void X86GNULDBackend::updateAddend(Relocation& pReloc,
258                                   const LDSymbol& pInputSym,
259                                   const Layout& pLayout) const
260{
261  // Update value keep in addend if we meet a section symbol
262  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
263    pReloc.setAddend(pLayout.getOutputOffset(
264                     *pInputSym.fragRef()) + pReloc.addend());
265  }
266}
267
268void X86GNULDBackend::scanLocalReloc(Relocation& pReloc,
269                                     const LDSymbol& pInputSym,
270                                     MCLinker& pLinker,
271                                     const MCLDInfo& pLDInfo,
272                                     const Output& pOutput)
273{
274  // rsym - The relocation target symbol
275  ResolveInfo* rsym = pReloc.symInfo();
276
277  updateAddend(pReloc, pInputSym, pLinker.getLayout());
278
279  switch(pReloc.type()){
280
281    case llvm::ELF::R_386_32:
282      // If buiding PIC object (shared library or PIC executable),
283      // a dynamic relocations with RELATIVE type to this location is needed.
284      // Reserve an entry in .rel.dyn
285      if (isOutputPIC(pOutput, pLDInfo)) {
286        // create .rel.dyn section if not exist
287        if (NULL == m_pRelDyn)
288          createX86RelDyn(pLinker, pOutput);
289        m_pRelDyn->reserveEntry(*m_pRelocFactory);
290        // set Rel bit
291        rsym->setReserved(rsym->reserved() | ReserveRel);
292      }
293      return;
294
295    case llvm::ELF::R_386_GOTOFF:
296    case llvm::ELF::R_386_GOTPC:
297      // A GOT section is needed
298      if (NULL == m_pGOT)
299        createX86GOT(pLinker, pOutput);
300      return;
301
302    case llvm::ELF::R_386_PC32:
303      return;
304
305    default:
306      fatal(diag::unsupported_relocation) << (int)pReloc.type()
307                                          << "mclinker@googlegroups.com";
308      break;
309  } // end switch
310}
311
312void X86GNULDBackend::scanGlobalReloc(Relocation& pReloc,
313                                      const LDSymbol& pInputSym,
314                                      MCLinker& pLinker,
315                                      const MCLDInfo& pLDInfo,
316                                      const Output& pOutput)
317{
318  // rsym - The relocation target symbol
319  ResolveInfo* rsym = pReloc.symInfo();
320
321  switch(pReloc.type()) {
322    case llvm::ELF::R_386_32:
323      // Absolute relocation type, symbol may needs PLT entry or
324      // dynamic relocation entry
325      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
326        // create plt for this symbol if it does not have one
327        if (!(rsym->reserved() & ReservePLT)){
328          // Create .got section if it dosen't exist
329          if (NULL == m_pGOTPLT)
330            createX86GOTPLT(pLinker, pOutput);
331          // create .plt and .rel.plt if not exist
332          if (NULL == m_pPLT)
333            createX86PLTandRelPLT(pLinker, pOutput);
334          // Symbol needs PLT entry, we need to reserve a PLT entry
335          // and the corresponding GOT and dynamic relocation entry
336          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
337          // when calling X86PLT->reserveEntry())
338          m_pPLT->reserveEntry();
339          m_pRelPLT->reserveEntry(*m_pRelocFactory);
340          // set PLT bit
341          rsym->setReserved(rsym->reserved() | ReservePLT);
342        }
343      }
344
345      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
346                            pLDInfo, pOutput, true)) {
347        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
348        // create .rel.dyn section if not exist
349        if (NULL == m_pRelDyn)
350          createX86RelDyn(pLinker, pOutput);
351        m_pRelDyn->reserveEntry(*m_pRelocFactory);
352        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
353                          pOutput)) {
354          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
355          addCopyReloc(*cpy_sym.resolveInfo());
356        }
357        else {
358          // set Rel bit
359          rsym->setReserved(rsym->reserved() | ReserveRel);
360        }
361      }
362      return;
363
364    case llvm::ELF::R_386_GOTOFF:
365    case llvm::ELF::R_386_GOTPC: {
366      // A GOT section is needed
367      if (NULL == m_pGOT)
368        createX86GOT(pLinker, pOutput);
369      return;
370    }
371
372    case llvm::ELF::R_386_PLT32:
373      // A PLT entry is needed when building shared library
374
375      // return if we already create plt for this symbol
376      if (rsym->reserved() & ReservePLT)
377        return;
378
379      // if symbol is defined in the ouput file and it's not
380      // preemptible, no need plt
381      if (rsym->isDefine() && !rsym->isDyn() &&
382         !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
383        return;
384      }
385
386      // Create .got section if it dosen't exist
387      if (NULL == m_pGOTPLT)
388         createX86GOTPLT(pLinker, pOutput);
389      // create .plt and .rel.plt if not exist
390      if (NULL == m_pPLT)
391         createX86PLTandRelPLT(pLinker, pOutput);
392      // Symbol needs PLT entry, we need to reserve a PLT entry
393      // and the corresponding GOT and dynamic relocation entry
394      // in .got and .rel.plt. (GOT entry will be reserved simultaneously
395      // when calling X86PLT->reserveEntry())
396      m_pPLT->reserveEntry();
397      m_pRelPLT->reserveEntry(*m_pRelocFactory);
398      // set PLT bit
399      rsym->setReserved(rsym->reserved() | ReservePLT);
400      return;
401
402    case llvm::ELF::R_386_GOT32:
403      // Symbol needs GOT entry, reserve entry in .got
404      // return if we already create GOT for this symbol
405      if (rsym->reserved() & (ReserveGOT | GOTRel))
406        return;
407      if (NULL == m_pGOT)
408        createX86GOT(pLinker, pOutput);
409      m_pGOT->reserveEntry();
410      // If building shared object or the symbol is undefined, a dynamic
411      // relocation is needed to relocate this GOT entry. Reserve an
412      // entry in .rel.dyn
413      if (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
414        // create .rel.dyn section if not exist
415        if (NULL == m_pRelDyn)
416          createX86RelDyn(pLinker, pOutput);
417        m_pRelDyn->reserveEntry(*m_pRelocFactory);
418        // set GOTRel bit
419        rsym->setReserved(rsym->reserved() | GOTRel);
420        return;
421      }
422      // set GOT bit
423      rsym->setReserved(rsym->reserved() | ReserveGOT);
424      return;
425
426    case llvm::ELF::R_386_PC32:
427
428      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput) &&
429          pOutput.type() != Output::DynObj) {
430        // create plt for this symbol if it does not have one
431        if (!(rsym->reserved() & ReservePLT)){
432          // Create .got section if it dosen't exist
433          if (NULL == m_pGOTPLT)
434            createX86GOTPLT(pLinker, pOutput);
435          // create .plt and .rel.plt if not exist
436          if (NULL == m_pPLT)
437            createX86PLTandRelPLT(pLinker, pOutput);
438          // Symbol needs PLT entry, we need to reserve a PLT entry
439          // and the corresponding GOT and dynamic relocation entry
440          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
441          // when calling X86PLT->reserveEntry())
442          m_pPLT->reserveEntry();
443          m_pRelPLT->reserveEntry(*m_pRelocFactory);
444          // set PLT bit
445          rsym->setReserved(rsym->reserved() | ReservePLT);
446        }
447      }
448
449      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
450                            pLDInfo, pOutput, false)) {
451        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
452        // create .rel.dyn section if not exist
453        if (NULL == m_pRelDyn)
454          createX86RelDyn(pLinker, pOutput);
455        m_pRelDyn->reserveEntry(*m_pRelocFactory);
456        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
457                          pOutput)) {
458          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
459          addCopyReloc(*cpy_sym.resolveInfo());
460        }
461        else {
462          // set Rel bit
463          rsym->setReserved(rsym->reserved() | ReserveRel);
464        }
465      }
466      return;
467    default: {
468      fatal(diag::unsupported_relocation) << (int)pReloc.type()
469                                          << "mclinker@googlegroups.com";
470      break;
471    }
472  } // end switch
473}
474
475void X86GNULDBackend::scanRelocation(Relocation& pReloc,
476                                     const LDSymbol& pInputSym,
477                                     MCLinker& pLinker,
478                                     const MCLDInfo& pLDInfo,
479                                     const Output& pOutput,
480                                     const LDSection& pSection)
481{
482  // rsym - The relocation target symbol
483  ResolveInfo* rsym = pReloc.symInfo();
484  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
485
486  assert(NULL != pSection.getLink());
487  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
488    if (rsym->isLocal()) {
489      updateAddend(pReloc, pInputSym, pLinker.getLayout());
490    }
491    return;
492  }
493
494  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
495  // entries should be created.
496  // FIXME: Below judgements concern only .so is generated as output
497  // FIXME: Below judgements concren nothing about TLS related relocation
498
499  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got.plt
500  // section is needed
501  if (NULL == m_pGOTPLT && NULL != m_pGOTSymbol) {
502    if (rsym == m_pGOTSymbol->resolveInfo()) {
503      createX86GOTPLT(pLinker, pOutput);
504    }
505  }
506
507  // rsym is local
508  if (rsym->isLocal())
509    scanLocalReloc(pReloc, pInputSym,  pLinker, pLDInfo, pOutput);
510
511  // rsym is external
512  else
513    scanGlobalReloc(pReloc, pInputSym ,pLinker, pLDInfo, pOutput);
514
515}
516
517uint64_t X86GNULDBackend::emitSectionData(const Output& pOutput,
518                                          const LDSection& pSection,
519                                          const MCLDInfo& pInfo,
520                                          const Layout& pLayout,
521                                          MemoryRegion& pRegion) const
522{
523  assert(pRegion.size() && "Size of MemoryRegion is zero!");
524
525  const ELFFileFormat* FileFormat = getOutputFormat(pOutput);
526  assert(FileFormat &&
527         "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
528
529  unsigned int EntrySize = 0;
530  uint64_t RegionSize = 0;
531
532  if (&pSection == &(FileFormat->getPLT())) {
533    assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
534
535    unsigned char* buffer = pRegion.getBuffer();
536
537    m_pPLT->applyPLT0();
538    m_pPLT->applyPLT1();
539
540    X86PLT::iterator it = m_pPLT->begin();
541    unsigned int plt0_size = llvm::cast<X86PLT0>((*it)).getEntrySize();
542
543    memcpy(buffer, llvm::cast<X86PLT0>((*it)).getContent(), plt0_size);
544    RegionSize += plt0_size;
545    ++it;
546
547    X86PLT1* plt1 = 0;
548    X86PLT::iterator ie = m_pPLT->end();
549    while (it != ie) {
550      plt1 = &(llvm::cast<X86PLT1>(*it));
551      EntrySize = plt1->getEntrySize();
552      memcpy(buffer + RegionSize, plt1->getContent(), EntrySize);
553      RegionSize += EntrySize;
554      ++it;
555    }
556  }
557
558  else if (&pSection == &(FileFormat->getGOT())) {
559    assert(m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
560
561    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
562
563    GOTEntry* got = 0;
564    EntrySize = m_pGOT->getEntrySize();
565
566    for (X86GOT::iterator it = m_pGOT->begin(),
567         ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
568      got = &(llvm::cast<GOTEntry>((*it)));
569      *buffer = static_cast<uint32_t>(got->getContent());
570      RegionSize += EntrySize;
571    }
572  }
573
574  else if (&pSection == &(FileFormat->getGOTPLT())) {
575    assert(m_pGOTPLT && "emitSectionData failed, m_pGOTPLT is NULL!");
576    m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
577
578    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
579
580    GOTEntry* got = 0;
581    EntrySize = m_pGOTPLT->getEntrySize();
582
583    for (X86GOTPLT::iterator it = m_pGOTPLT->begin(),
584         ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
585      got = &(llvm::cast<GOTEntry>((*it)));
586      *buffer = static_cast<uint32_t>(got->getContent());
587      RegionSize += EntrySize;
588    }
589  }
590
591  else {
592    fatal(diag::unrecognized_output_sectoin)
593            << pSection.name()
594            << "mclinker@googlegroups.com";
595  }
596  return RegionSize;
597}
598uint32_t X86GNULDBackend::machine() const
599{
600  return llvm::ELF::EM_386;
601}
602
603X86GOT& X86GNULDBackend::getGOT()
604{
605  assert(NULL != m_pGOT);
606  return *m_pGOT;
607}
608
609const X86GOT& X86GNULDBackend::getGOT() const
610{
611  assert(NULL != m_pGOT);
612  return *m_pGOT;
613}
614
615X86GOTPLT& X86GNULDBackend::getGOTPLT()
616{
617  assert(NULL != m_pGOTPLT);
618  return *m_pGOTPLT;
619}
620
621const X86GOTPLT& X86GNULDBackend::getGOTPLT() const
622{
623  assert(NULL != m_pGOTPLT);
624  return *m_pGOTPLT;
625}
626
627X86PLT& X86GNULDBackend::getPLT()
628{
629  assert(NULL != m_pPLT && "PLT section not exist");
630  return *m_pPLT;
631}
632
633const X86PLT& X86GNULDBackend::getPLT() const
634{
635  assert(NULL != m_pPLT && "PLT section not exist");
636  return *m_pPLT;
637}
638
639OutputRelocSection& X86GNULDBackend::getRelDyn()
640{
641  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
642  return *m_pRelDyn;
643}
644
645const OutputRelocSection& X86GNULDBackend::getRelDyn() const
646{
647  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
648  return *m_pRelDyn;
649}
650
651OutputRelocSection& X86GNULDBackend::getRelPLT()
652{
653  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
654  return *m_pRelPLT;
655}
656
657const OutputRelocSection& X86GNULDBackend::getRelPLT() const
658{
659  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
660  return *m_pRelPLT;
661}
662
663unsigned int
664X86GNULDBackend::getTargetSectionOrder(const Output& pOutput,
665                                       const LDSection& pSectHdr,
666                                       const MCLDInfo& pInfo) const
667{
668  const ELFFileFormat* file_format = getOutputFormat(pOutput);
669
670  if (&pSectHdr == &file_format->getGOT()) {
671    if (pInfo.options().hasNow())
672      return SHO_RELRO;
673    return SHO_RELRO_LAST;
674  }
675
676  if (&pSectHdr == &file_format->getGOTPLT()) {
677    if (pInfo.options().hasNow())
678      return SHO_RELRO;
679    return SHO_NON_RELRO_FIRST;
680  }
681
682  if (&pSectHdr == &file_format->getPLT())
683    return SHO_PLT;
684
685  return SHO_UNDEFINED;
686}
687
688unsigned int X86GNULDBackend::bitclass() const
689{
690  return 32;
691}
692
693bool X86GNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
694{
695  return true;
696}
697
698void X86GNULDBackend::initTargetSections(MCLinker& pLinker)
699{
700}
701
702void X86GNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
703{
704  // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
705  // same name in input
706  m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
707                   "_GLOBAL_OFFSET_TABLE_",
708                   false,
709                   ResolveInfo::Object,
710                   ResolveInfo::Define,
711                   ResolveInfo::Local,
712                   0x0,  // size
713                   0x0,  // value
714                   NULL, // FragRef
715                   ResolveInfo::Hidden);
716}
717
718/// finalizeSymbol - finalize the symbol value
719bool X86GNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
720{
721  return true;
722}
723
724namespace mcld {
725
726//===----------------------------------------------------------------------===//
727/// createX86LDBackend - the help funtion to create corresponding X86LDBackend
728///
729TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget,
730                                    const std::string& pTriple)
731{
732  Triple theTriple(pTriple);
733  if (theTriple.isOSDarwin()) {
734    assert(0 && "MachO linker is not supported yet");
735    /**
736    return new X86MachOLDBackend(createX86MachOArchiveReader,
737                               createX86MachOObjectReader,
738                               createX86MachOObjectWriter);
739    **/
740  }
741  if (theTriple.isOSWindows()) {
742    assert(0 && "COFF linker is not supported yet");
743    /**
744    return new X86COFFLDBackend(createX86COFFArchiveReader,
745                               createX86COFFObjectReader,
746                               createX86COFFObjectWriter);
747    **/
748  }
749  return new X86GNULDBackend();
750}
751
752} // namespace of mcld
753
754//=============================
755// Force static initialization.
756extern "C" void LLVMInitializeX86LDBackend() {
757  // Register the linker backend
758  mcld::TargetRegistry::RegisterTargetLDBackend(TheX86Target, createX86LDBackend);
759}
760