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