X86LDBackend.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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 "X86RelocationFactory.h"
13
14#include <llvm/ADT/Triple.h>
15#include <llvm/Support/Casting.h>
16
17#include <mcld/LinkerConfig.h>
18#include <mcld/IRBuilder.h>
19#include <mcld/Fragment/FillFragment.h>
20#include <mcld/Fragment/RegionFragment.h>
21#include <mcld/Fragment/FragmentLinker.h>
22#include <mcld/Support/MemoryRegion.h>
23#include <mcld/Support/MsgHandling.h>
24#include <mcld/Support/TargetRegistry.h>
25#include <mcld/Object/ObjectBuilder.h>
26
27#include <cstring>
28
29using namespace mcld;
30
31//===----------------------------------------------------------------------===//
32// X86GNULDBackend
33//===----------------------------------------------------------------------===//
34X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig)
35  : GNULDBackend(pConfig),
36    m_pRelocFactory(NULL),
37    m_pGOT(NULL),
38    m_pPLT(NULL),
39    m_pGOTPLT(NULL),
40    m_pRelDyn(NULL),
41    m_pRelPLT(NULL),
42    m_pDynamic(NULL),
43    m_pGOTSymbol(NULL) {
44}
45
46X86GNULDBackend::~X86GNULDBackend()
47{
48  delete m_pRelocFactory;
49  delete m_pGOT;
50  delete m_pPLT;
51  delete m_pGOTPLT;
52  delete m_pRelDyn;
53  delete m_pRelPLT;
54  delete m_pDynamic;
55}
56
57RelocationFactory* X86GNULDBackend::getRelocFactory()
58{
59  assert(NULL != m_pRelocFactory);
60  return m_pRelocFactory;
61}
62
63bool X86GNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
64{
65  if (NULL == m_pRelocFactory) {
66    m_pRelocFactory = new X86RelocationFactory(1024, *this);
67    m_pRelocFactory->setFragmentLinker(pLinker);
68  }
69  return true;
70}
71
72void X86GNULDBackend::doPreLayout(FragmentLinker& pLinker)
73{
74  // set .got.plt size
75  // when building shared object, the .got section is must
76  if (LinkerConfig::Object != config().codeGenType()) {
77    if (LinkerConfig::DynObj == config().codeGenType() ||
78        m_pGOTPLT->hasGOT1() ||
79        NULL != m_pGOTSymbol) {
80      m_pGOTPLT->finalizeSectionSize();
81      defineGOTSymbol(pLinker);
82    }
83
84    // set .got size
85    if (!m_pGOT->empty())
86      m_pGOT->finalizeSectionSize();
87
88    // set .plt size
89    if (m_pPLT->hasPLT1())
90      m_pPLT->finalizeSectionSize();
91
92    // set .rel.dyn size
93    if (!m_pRelDyn->empty())
94      m_pRelDyn->finalizeSectionSize();
95
96    // set .rel.plt size
97    if (!m_pRelPLT->empty())
98      m_pRelPLT->finalizeSectionSize();
99  }
100}
101
102void X86GNULDBackend::doPostLayout(Module& pModule,
103                                   FragmentLinker& pLinker)
104{
105}
106
107/// dynamic - the dynamic section of the target machine.
108/// Use co-variant return type to return its own dynamic section.
109X86ELFDynamic& X86GNULDBackend::dynamic()
110{
111  if (NULL == m_pDynamic)
112    m_pDynamic = new X86ELFDynamic(*this);
113
114  return *m_pDynamic;
115}
116
117/// dynamic - the dynamic section of the target machine.
118/// Use co-variant return type to return its own dynamic section.
119const X86ELFDynamic& X86GNULDBackend::dynamic() const
120{
121  assert( NULL != m_pDynamic);
122  return *m_pDynamic;
123}
124
125void X86GNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
126{
127  // define symbol _GLOBAL_OFFSET_TABLE_
128  if (m_pGOTSymbol != NULL) {
129    pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
130                     "_GLOBAL_OFFSET_TABLE_",
131                     false,
132                     ResolveInfo::Object,
133                     ResolveInfo::Define,
134                     ResolveInfo::Local,
135                     0x0, // size
136                     0x0, // value
137                     FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
138                     ResolveInfo::Hidden);
139  }
140  else {
141    m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
142                     "_GLOBAL_OFFSET_TABLE_",
143                     false,
144                     ResolveInfo::Object,
145                     ResolveInfo::Define,
146                     ResolveInfo::Local,
147                     0x0, // size
148                     0x0, // value
149                     FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
150                     ResolveInfo::Hidden);
151  }
152}
153
154void X86GNULDBackend::addCopyReloc(ResolveInfo& pSym)
155{
156  Relocation& rel_entry = *m_pRelDyn->consumeEntry();
157  rel_entry.setType(llvm::ELF::R_386_COPY);
158  assert(pSym.outSymbol()->hasFragRef());
159  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
160  rel_entry.setSymInfo(&pSym);
161}
162
163/// defineSymbolforCopyReloc
164/// For a symbol needing copy relocation, define a copy symbol in the BSS
165/// section and all other reference to this symbol should refer to this
166/// copy.
167/// @note This is executed at `scan relocation' stage.
168LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(FragmentLinker& pLinker,
169                                                    const ResolveInfo& pSym)
170{
171  // get or create corresponding BSS LDSection
172  LDSection* bss_sect_hdr = NULL;
173  ELFFileFormat* file_format = getOutputFormat();
174  if (ResolveInfo::ThreadLocal == pSym.type())
175    bss_sect_hdr = &file_format->getTBSS();
176  else
177    bss_sect_hdr = &file_format->getBSS();
178
179  // get or create corresponding BSS SectionData
180  assert(NULL != bss_sect_hdr);
181  SectionData* bss_section = NULL;
182  if (bss_sect_hdr->hasSectionData())
183    bss_section = bss_sect_hdr->getSectionData();
184  else
185    bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr);
186
187  // Determine the alignment by the symbol value
188  // FIXME: here we use the largest alignment
189  uint32_t addralign = bitclass() / 8;
190
191  // allocate space in BSS for the copy symbol
192  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
193  uint64_t size = ObjectBuilder::AppendFragment(*frag,
194                                                *bss_section,
195                                                addralign);
196  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
197
198  // change symbol binding to Global if it's a weak symbol
199  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
200  if (binding == ResolveInfo::Weak)
201    binding = ResolveInfo::Global;
202
203  // Define the copy symbol in the bss section and resolve it
204  LDSymbol* cpy_sym =
205           pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
206                      pSym.name(),
207                      false,
208                      (ResolveInfo::Type)pSym.type(),
209                      ResolveInfo::Define,
210                      binding,
211                      pSym.size(),  // size
212                      0x0,          // value
213                      FragmentRef::Create(*frag, 0x0),
214                      (ResolveInfo::Visibility)pSym.other());
215
216  return *cpy_sym;
217}
218
219void X86GNULDBackend::scanLocalReloc(Relocation& pReloc,
220                                     FragmentLinker& pLinker,
221                                     Module& pModule,
222                                     const LDSection& pSection)
223{
224  // rsym - The relocation target symbol
225  ResolveInfo* rsym = pReloc.symInfo();
226
227  switch(pReloc.type()){
228
229    case llvm::ELF::R_386_32:
230    case llvm::ELF::R_386_16:
231    case llvm::ELF::R_386_8:
232      // If buiding PIC object (shared library or PIC executable),
233      // a dynamic relocations with RELATIVE type to this location is needed.
234      // Reserve an entry in .rel.dyn
235      if (pLinker.isOutputPIC()) {
236        m_pRelDyn->reserveEntry(*m_pRelocFactory);
237        // set Rel bit
238        rsym->setReserved(rsym->reserved() | ReserveRel);
239      }
240      return;
241
242    case llvm::ELF::R_386_GOTOFF:
243    case llvm::ELF::R_386_GOTPC:
244      // FIXME: A GOT section is needed
245      return;
246
247    case llvm::ELF::R_386_GOT32:
248      // Symbol needs GOT entry, reserve entry in .got
249      // return if we already create GOT for this symbol
250      if (rsym->reserved() & (ReserveGOT | GOTRel))
251        return;
252      // FIXME: check STT_GNU_IFUNC symbol
253      m_pGOT->reserve();
254      // If building shared object or the symbol is undefined, a dynamic
255      // relocation is needed to relocate this GOT entry. Reserve an
256      // entry in .rel.dyn
257      if (LinkerConfig::DynObj ==
258                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
259        m_pRelDyn->reserveEntry(*m_pRelocFactory);
260        // set GOTRel bit
261        rsym->setReserved(rsym->reserved() | GOTRel);
262        return;
263      }
264      // set GOT bit
265      rsym->setReserved(rsym->reserved() | ReserveGOT);
266      return;
267
268    case llvm::ELF::R_386_PC32:
269    case llvm::ELF::R_386_PC16:
270    case llvm::ELF::R_386_PC8:
271      return;
272
273    case llvm::ELF::R_386_TLS_GD: {
274      // FIXME: no linker optimization for TLS relocation
275      if (rsym->reserved() & GOTRel)
276        return;
277      m_pGOT->reserve(2);
278      // reserve an rel entry
279      m_pRelDyn->reserveEntry(*m_pRelocFactory);
280      // set GOTRel bit
281      rsym->setReserved(rsym->reserved() | GOTRel);
282      // define the section symbol for .tdata or .tbss
283      // the target symbol of the created dynamic relocation should be the
284      // section symbol of the section which this symbol defined. so we
285      // need to define that section symbol here
286      ELFFileFormat* file_format = getOutputFormat();
287      const LDSection* sym_sect =
288               &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
289      if (&file_format->getTData() == sym_sect) {
290        if (NULL == f_pTDATA)
291          f_pTDATA = pModule.getSectionSymbolSet().get(*sym_sect);
292      }
293      else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) {
294        if (NULL == f_pTBSS)
295          f_pTBSS = pModule.getSectionSymbolSet().get(*sym_sect);
296      }
297      else
298        error(diag::invalid_tls) << rsym->name() << sym_sect->name();
299      return;
300    }
301
302    case llvm::ELF::R_386_TLS_LDM:
303      getTLSModuleID();
304      return;
305
306    case llvm::ELF::R_386_TLS_LDO_32:
307      return;
308
309    case llvm::ELF::R_386_TLS_IE:
310      setHasStaticTLS();
311      // if buildint shared object, a RELATIVE dynamic relocation is needed
312      if (LinkerConfig::DynObj == config().codeGenType()) {
313        m_pRelDyn->reserveEntry(*m_pRelocFactory);
314        rsym->setReserved(rsym->reserved() | ReserveRel);
315      }
316      if (rsym->reserved() & GOTRel)
317        return;
318      // reserve got and dyn relocation entries for tp-relative offset
319      m_pGOT->reserve();
320      m_pRelDyn->reserveEntry(*m_pRelocFactory);
321      // set GOTRel bit
322      rsym->setReserved(rsym->reserved() | GOTRel);
323      m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
324      return;
325
326    case llvm::ELF::R_386_TLS_GOTIE:
327      setHasStaticTLS();
328      if (rsym->reserved() & GOTRel)
329        return;
330      // reserve got and dyn relocation entries for tp-relative offset
331      m_pGOT->reserve();
332      m_pRelDyn->reserveEntry(*m_pRelocFactory);
333      // set GOTRel bit
334      rsym->setReserved(rsym->reserved() | GOTRel);
335      m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
336      return;
337
338    case llvm::ELF::R_386_TLS_LE:
339    case llvm::ELF::R_386_TLS_LE_32:
340      setHasStaticTLS();
341      // if buildint shared object, a dynamic relocation is needed
342      if (LinkerConfig::DynObj == config().codeGenType()) {
343        m_pRelDyn->reserveEntry(*m_pRelocFactory);
344        rsym->setReserved(rsym->reserved() | ReserveRel);
345        // the target symbol of the dynamic relocation is rsym, so we need to
346        // emit it into .dynsym
347        assert(NULL != rsym->outSymbol());
348        m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
349      }
350      return;
351
352    default:
353      fatal(diag::unsupported_relocation) << (int)pReloc.type()
354                                          << "mclinker@googlegroups.com";
355      break;
356  } // end switch
357}
358
359void X86GNULDBackend::scanGlobalReloc(Relocation& pReloc,
360                                      FragmentLinker& pLinker,
361                                      Module& pModule,
362                                      const LDSection& pSection)
363{
364  // rsym - The relocation target symbol
365  ResolveInfo* rsym = pReloc.symInfo();
366
367  switch(pReloc.type()) {
368    case llvm::ELF::R_386_32:
369    case llvm::ELF::R_386_16:
370    case llvm::ELF::R_386_8:
371      // Absolute relocation type, symbol may needs PLT entry or
372      // dynamic relocation entry
373      if (symbolNeedsPLT(pLinker, *rsym)) {
374        // create plt for this symbol if it does not have one
375        if (!(rsym->reserved() & ReservePLT)){
376          // Symbol needs PLT entry, we need to reserve a PLT entry
377          // and the corresponding GOT and dynamic relocation entry
378          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
379          // when calling X86PLT->reserveEntry())
380          m_pPLT->reserveEntry();
381          m_pGOTPLT->reserve();
382          m_pRelPLT->reserveEntry(*m_pRelocFactory);
383          // set PLT bit
384          rsym->setReserved(rsym->reserved() | ReservePLT);
385        }
386      }
387
388      if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
389                                                                       true)) {
390        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
391        m_pRelDyn->reserveEntry(*m_pRelocFactory);
392        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
393          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
394          addCopyReloc(*cpy_sym.resolveInfo());
395        }
396        else {
397          // set Rel bit
398          rsym->setReserved(rsym->reserved() | ReserveRel);
399        }
400      }
401      return;
402
403    case llvm::ELF::R_386_GOTOFF:
404    case llvm::ELF::R_386_GOTPC: {
405      // FIXME: A GOT section is needed
406      return;
407    }
408
409    case llvm::ELF::R_386_PLT32:
410      // A PLT entry is needed when building shared library
411
412      // return if we already create plt for this symbol
413      if (rsym->reserved() & ReservePLT)
414        return;
415
416      // if the symbol's value can be decided at link time, then no need plt
417      if (symbolFinalValueIsKnown(pLinker, *rsym))
418        return;
419
420      // if symbol is defined in the ouput file and it's not
421      // preemptible, no need plt
422      if (rsym->isDefine() && !rsym->isDyn() &&
423         !isSymbolPreemptible(*rsym)) {
424        return;
425      }
426
427      // Symbol needs PLT entry, we need to reserve a PLT entry
428      // and the corresponding GOT and dynamic relocation entry
429      // in .got and .rel.plt. (GOT entry will be reserved simultaneously
430      // when calling X86PLT->reserveEntry())
431      m_pPLT->reserveEntry();
432      m_pGOTPLT->reserve();
433      m_pRelPLT->reserveEntry(*m_pRelocFactory);
434      // set PLT bit
435      rsym->setReserved(rsym->reserved() | ReservePLT);
436      return;
437
438    case llvm::ELF::R_386_GOT32:
439      // Symbol needs GOT entry, reserve entry in .got
440      // return if we already create GOT for this symbol
441      if (rsym->reserved() & (ReserveGOT | GOTRel))
442        return;
443      m_pGOT->reserve();
444      // If building shared object or the symbol is undefined, a dynamic
445      // relocation is needed to relocate this GOT entry. Reserve an
446      // entry in .rel.dyn
447      if (LinkerConfig::DynObj ==
448                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
449        m_pRelDyn->reserveEntry(*m_pRelocFactory);
450        // set GOTRel bit
451        rsym->setReserved(rsym->reserved() | GOTRel);
452        return;
453      }
454      // set GOT bit
455      rsym->setReserved(rsym->reserved() | ReserveGOT);
456      return;
457
458    case llvm::ELF::R_386_PC32:
459    case llvm::ELF::R_386_PC16:
460    case llvm::ELF::R_386_PC8:
461
462      if (symbolNeedsPLT(pLinker, *rsym) &&
463                               LinkerConfig::DynObj != config().codeGenType()) {
464        // create plt for this symbol if it does not have one
465        if (!(rsym->reserved() & ReservePLT)){
466          // Symbol needs PLT entry, we need to reserve a PLT entry
467          // and the corresponding GOT and dynamic relocation entry
468          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
469          // when calling X86PLT->reserveEntry())
470          m_pPLT->reserveEntry();
471          m_pGOTPLT->reserve();
472          m_pRelPLT->reserveEntry(*m_pRelocFactory);
473          // set PLT bit
474          rsym->setReserved(rsym->reserved() | ReservePLT);
475        }
476      }
477
478      if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
479                                                                      false)) {
480        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
481        m_pRelDyn->reserveEntry(*m_pRelocFactory);
482        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
483          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
484          addCopyReloc(*cpy_sym.resolveInfo());
485        }
486        else {
487          // set Rel bit
488          rsym->setReserved(rsym->reserved() | ReserveRel);
489        }
490      }
491      return;
492
493    case llvm::ELF::R_386_TLS_GD: {
494      // FIXME: no linker optimization for TLS relocation
495      if (rsym->reserved() & GOTRel)
496        return;
497      // reserve two pairs of got entry and dynamic relocation
498      m_pGOT->reserve(2);
499      m_pRelDyn->reserveEntry(*m_pRelocFactory, 2);
500      // set GOTRel bit
501      rsym->setReserved(rsym->reserved() | GOTRel);
502      return;
503    }
504
505    case llvm::ELF::R_386_TLS_LDM:
506      getTLSModuleID();
507      return;
508
509    case llvm::ELF::R_386_TLS_LDO_32:
510      return;
511
512    case llvm::ELF::R_386_TLS_IE:
513      setHasStaticTLS();
514      // if buildint shared object, a RELATIVE dynamic relocation is needed
515      if (LinkerConfig::DynObj == config().codeGenType()) {
516        m_pRelDyn->reserveEntry(*m_pRelocFactory);
517        rsym->setReserved(rsym->reserved() | ReserveRel);
518      }
519      if (rsym->reserved() & GOTRel)
520        return;
521      // reserve got and dyn relocation entries for tp-relative offset
522      m_pGOT->reserve();
523      m_pRelDyn->reserveEntry(*m_pRelocFactory);
524      // set GOTRel bit
525      rsym->setReserved(rsym->reserved() | GOTRel);
526      return;
527
528    case llvm::ELF::R_386_TLS_GOTIE:
529      setHasStaticTLS();
530      if (rsym->reserved() & GOTRel)
531        return;
532      // reserve got and dyn relocation entries for tp-relative offset
533      m_pGOT->reserve();
534      m_pRelDyn->reserveEntry(*m_pRelocFactory);
535      // set GOTRel bit
536      rsym->setReserved(rsym->reserved() | GOTRel);
537      return;
538
539    case llvm::ELF::R_386_TLS_LE:
540    case llvm::ELF::R_386_TLS_LE_32:
541      setHasStaticTLS();
542      // if buildint shared object, a dynamic relocation is needed
543      if (LinkerConfig::DynObj == config().codeGenType()) {
544        m_pRelDyn->reserveEntry(*m_pRelocFactory);
545        rsym->setReserved(rsym->reserved() | ReserveRel);
546      }
547      return;
548
549    default: {
550      fatal(diag::unsupported_relocation) << (int)pReloc.type()
551                                          << "mclinker@googlegroups.com";
552      break;
553    }
554  } // end switch
555}
556
557void X86GNULDBackend::scanRelocation(Relocation& pReloc,
558                                     FragmentLinker& pLinker,
559                                     Module& pModule,
560                                     const LDSection& pSection)
561{
562  if (LinkerConfig::Object == config().codeGenType())
563    return;
564  // rsym - The relocation target symbol
565  ResolveInfo* rsym = pReloc.symInfo();
566  assert(NULL != rsym &&
567         "ResolveInfo of relocation not set while scanRelocation");
568
569  pReloc.updateAddend();
570  if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
571    return;
572
573  // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation
574  // entries should be created.
575  if (rsym->isLocal()) // rsym is local
576    scanLocalReloc(pReloc, pLinker, pModule, pSection);
577  else // rsym is external
578    scanGlobalReloc(pReloc, pLinker, pModule, pSection);
579
580  // check if we shoule issue undefined reference for the relocation target
581  // symbol
582  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
583    fatal(diag::undefined_reference) << rsym->name();
584
585  if ((rsym->reserved() & ReserveRel) != 0x0) {
586    // set hasTextRelSection if needed
587    checkAndSetHasTextRel(pSection);
588  }
589}
590
591uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
592                                          MemoryRegion& pRegion) const
593{
594  assert(pRegion.size() && "Size of MemoryRegion is zero!");
595
596  const ELFFileFormat* FileFormat = getOutputFormat();
597  assert(FileFormat &&
598         "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
599
600  unsigned int EntrySize = 0;
601  uint64_t RegionSize = 0;
602
603  if (&pSection == &(FileFormat->getPLT())) {
604    assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
605
606    unsigned char* buffer = pRegion.getBuffer();
607
608    m_pPLT->applyPLT0();
609    m_pPLT->applyPLT1();
610    X86PLT::iterator it = m_pPLT->begin();
611    unsigned int plt0_size = llvm::cast<X86PLT0>((*it)).getEntrySize();
612
613    memcpy(buffer, llvm::cast<X86PLT0>((*it)).getContent(), plt0_size);
614    RegionSize += plt0_size;
615    ++it;
616
617    X86PLT1* plt1 = 0;
618    X86PLT::iterator ie = m_pPLT->end();
619    while (it != ie) {
620      plt1 = &(llvm::cast<X86PLT1>(*it));
621      EntrySize = plt1->getEntrySize();
622      memcpy(buffer + RegionSize, plt1->getContent(), EntrySize);
623      RegionSize += EntrySize;
624      ++it;
625    }
626  }
627
628  else if (&pSection == &(FileFormat->getGOT())) {
629    assert(m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
630
631    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
632
633    GOT::Entry* got = 0;
634    EntrySize = m_pGOT->getEntrySize();
635
636    for (X86GOT::iterator it = m_pGOT->begin(),
637         ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
638      got = &(llvm::cast<GOT::Entry>((*it)));
639      *buffer = static_cast<uint32_t>(got->getContent());
640      RegionSize += EntrySize;
641    }
642  }
643
644  else if (&pSection == &(FileFormat->getGOTPLT())) {
645    assert(m_pGOTPLT && "emitSectionData failed, m_pGOTPLT is NULL!");
646    m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
647    m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
648
649    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
650
651    GOT::Entry* got = 0;
652    EntrySize = m_pGOTPLT->getEntrySize();
653
654    for (X86GOTPLT::iterator it = m_pGOTPLT->begin(),
655         ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
656      got = &(llvm::cast<GOT::Entry>((*it)));
657      *buffer = static_cast<uint32_t>(got->getContent());
658      RegionSize += EntrySize;
659    }
660  }
661
662  else {
663    fatal(diag::unrecognized_output_sectoin)
664            << pSection.name()
665            << "mclinker@googlegroups.com";
666  }
667  return RegionSize;
668}
669
670uint32_t X86GNULDBackend::machine() const
671{
672  return llvm::ELF::EM_386;
673}
674
675X86GOT& X86GNULDBackend::getGOT()
676{
677  assert(NULL != m_pGOT);
678  return *m_pGOT;
679}
680
681const X86GOT& X86GNULDBackend::getGOT() const
682{
683  assert(NULL != m_pGOT);
684  return *m_pGOT;
685}
686
687X86GOTPLT& X86GNULDBackend::getGOTPLT()
688{
689  assert(NULL != m_pGOTPLT);
690  return *m_pGOTPLT;
691}
692
693const X86GOTPLT& X86GNULDBackend::getGOTPLT() const
694{
695  assert(NULL != m_pGOTPLT);
696  return *m_pGOTPLT;
697}
698
699X86PLT& X86GNULDBackend::getPLT()
700{
701  assert(NULL != m_pPLT && "PLT section not exist");
702  return *m_pPLT;
703}
704
705const X86PLT& X86GNULDBackend::getPLT() const
706{
707  assert(NULL != m_pPLT && "PLT section not exist");
708  return *m_pPLT;
709}
710
711OutputRelocSection& X86GNULDBackend::getRelDyn()
712{
713  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
714  return *m_pRelDyn;
715}
716
717const OutputRelocSection& X86GNULDBackend::getRelDyn() const
718{
719  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
720  return *m_pRelDyn;
721}
722
723// Create a GOT entry for the TLS module index
724GOT::Entry& X86GNULDBackend::getTLSModuleID()
725{
726  static GOT::Entry* got_entry = NULL;
727  if (NULL != got_entry)
728    return *got_entry;
729
730  // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
731  m_pGOT->reserve(2);
732  got_entry = m_pGOT->consume();
733  m_pGOT->consume()->setContent(0x0);
734
735  m_pRelDyn->reserveEntry(*m_pRelocFactory);
736  Relocation* rel_entry = m_pRelDyn->consumeEntry();
737  rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32);
738  rel_entry->targetRef().assign(*got_entry, 0x0);
739  rel_entry->setSymInfo(NULL);
740
741  return *got_entry;
742}
743
744OutputRelocSection& X86GNULDBackend::getRelPLT()
745{
746  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
747  return *m_pRelPLT;
748}
749
750const OutputRelocSection& X86GNULDBackend::getRelPLT() const
751{
752  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
753  return *m_pRelPLT;
754}
755
756unsigned int
757X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
758{
759  const ELFFileFormat* file_format = getOutputFormat();
760
761  if (&pSectHdr == &file_format->getGOT()) {
762    if (config().options().hasNow())
763      return SHO_RELRO;
764    return SHO_RELRO_LAST;
765  }
766
767  if (&pSectHdr == &file_format->getGOTPLT()) {
768    if (config().options().hasNow())
769      return SHO_RELRO;
770    return SHO_NON_RELRO_FIRST;
771  }
772
773  if (&pSectHdr == &file_format->getPLT())
774    return SHO_PLT;
775
776  return SHO_UNDEFINED;
777}
778
779unsigned int X86GNULDBackend::bitclass() const
780{
781  return 32;
782}
783
784void X86GNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
785{
786  if (LinkerConfig::Object != config().codeGenType()) {
787    ELFFileFormat* file_format = getOutputFormat();
788    // initialize .got
789    LDSection& got = file_format->getGOT();
790    m_pGOT = new X86GOT(got);
791
792    // initialize .got.plt
793    LDSection& gotplt = file_format->getGOTPLT();
794    m_pGOTPLT = new X86GOTPLT(gotplt);
795
796    // initialize .plt
797    LDSection& plt = file_format->getPLT();
798    m_pPLT = new X86PLT(plt,
799                        *m_pGOTPLT,
800                        config());
801
802    // initialize .rel.plt
803    LDSection& relplt = file_format->getRelPlt();
804    relplt.setLink(&plt);
805    m_pRelPLT = new OutputRelocSection(pModule,
806                                       relplt,
807                                       getRelEntrySize());
808    // initialize .rel.dyn
809    LDSection& reldyn = file_format->getRelDyn();
810    m_pRelDyn = new OutputRelocSection(pModule,
811                                       reldyn,
812                                       getRelEntrySize());
813  }
814}
815
816void X86GNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
817{
818  if (LinkerConfig::Object != config().codeGenType()) {
819    // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
820    // same name in input
821    m_pGOTSymbol =
822      pLinker.defineSymbol<FragmentLinker::AsRefered,
823                           FragmentLinker::Resolve>("_GLOBAL_OFFSET_TABLE_",
824                                                    false,
825                                                    ResolveInfo::Object,
826                                                    ResolveInfo::Define,
827                                                    ResolveInfo::Local,
828                                                    0x0,  // size
829                                                    0x0,  // value
830                                                    FragmentRef::Null(), // FragRef
831                                                    ResolveInfo::Hidden);
832  }
833}
834
835/// finalizeSymbol - finalize the symbol value
836bool X86GNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
837{
838  return true;
839}
840
841/// doCreateProgramHdrs - backend can implement this function to create the
842/// target-dependent segments
843void X86GNULDBackend::doCreateProgramHdrs(Module& pModule,
844                                          const FragmentLinker& pLinker)
845{
846  // TODO
847}
848
849namespace mcld {
850
851//===----------------------------------------------------------------------===//
852/// createX86LDBackend - the help funtion to create corresponding X86LDBackend
853///
854TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget,
855                                    const LinkerConfig& pConfig)
856{
857  if (pConfig.triple().isOSDarwin()) {
858    assert(0 && "MachO linker is not supported yet");
859    /**
860    return new X86MachOLDBackend(createX86MachOArchiveReader,
861                               createX86MachOObjectReader,
862                               createX86MachOObjectWriter);
863    **/
864  }
865  if (pConfig.triple().isOSWindows()) {
866    assert(0 && "COFF linker is not supported yet");
867    /**
868    return new X86COFFLDBackend(createX86COFFArchiveReader,
869                               createX86COFFObjectReader,
870                               createX86COFFObjectWriter);
871    **/
872  }
873  return new X86GNULDBackend(pConfig);
874}
875
876} // namespace of mcld
877
878//===----------------------------------------------------------------------===//
879// Force static initialization.
880//===----------------------------------------------------------------------===//
881extern "C" void MCLDInitializeX86LDBackend() {
882  // Register the linker backend
883  mcld::TargetRegistry::RegisterTargetLDBackend(TheX86Target, createX86LDBackend);
884}
885