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