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