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 <llvm/ADT/Triple.h>
16 #include <llvm/Support/Casting.h>
17
18 #include <mcld/LinkerConfig.h>
19 #include <mcld/IRBuilder.h>
20 #include <mcld/Fragment/FillFragment.h>
21 #include <mcld/Fragment/RegionFragment.h>
22 #include <mcld/Fragment/FragmentLinker.h>
23 #include <mcld/Support/MemoryRegion.h>
24 #include <mcld/Support/MsgHandling.h>
25 #include <mcld/Support/TargetRegistry.h>
26 #include <mcld/Object/ObjectBuilder.h>
27
28 #include <cstring>
29
30 using namespace mcld;
31
32 //===----------------------------------------------------------------------===//
33 // X86GNULDBackend
34 //===----------------------------------------------------------------------===//
X86GNULDBackend(const LinkerConfig & pConfig,GNUInfo * pInfo,Relocation::Type pCopyRel)35 X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig,
36 GNUInfo* pInfo,
37 Relocation::Type pCopyRel)
38 : GNULDBackend(pConfig, pInfo),
39 m_pRelocator(NULL),
40 m_pPLT(NULL),
41 m_pRelDyn(NULL),
42 m_pRelPLT(NULL),
43 m_pDynamic(NULL),
44 m_pGOTSymbol(NULL),
45 m_CopyRel(pCopyRel)
46 {
47 Triple::ArchType arch = pConfig.targets().triple().getArch();
48 assert (arch == Triple::x86 || arch == Triple::x86_64);
49 if (arch == Triple::x86 ||
50 pConfig.targets().triple().getEnvironment() == Triple::GNUX32) {
51 m_RelEntrySize = 8;
52 m_RelaEntrySize = 12;
53 if (arch == Triple::x86)
54 m_PointerRel = llvm::ELF::R_386_32;
55 else
56 m_PointerRel = llvm::ELF::R_X86_64_32;
57 }
58 else {
59 m_RelEntrySize = 16;
60 m_RelaEntrySize = 24;
61 m_PointerRel = llvm::ELF::R_X86_64_64;
62 }
63 }
64
~X86GNULDBackend()65 X86GNULDBackend::~X86GNULDBackend()
66 {
67 delete m_pRelocator;
68 delete m_pPLT;
69 delete m_pRelDyn;
70 delete m_pRelPLT;
71 delete m_pDynamic;
72 }
73
getRelocator()74 Relocator* X86GNULDBackend::getRelocator()
75 {
76 assert(NULL != m_pRelocator);
77 return m_pRelocator;
78 }
79
doPreLayout(IRBuilder & pBuilder)80 void X86GNULDBackend::doPreLayout(IRBuilder& pBuilder)
81 {
82 // initialize .dynamic data
83 if (!config().isCodeStatic() && NULL == m_pDynamic)
84 m_pDynamic = new X86ELFDynamic(*this, config());
85
86 // set .got.plt and .got sizes
87 // when building shared object, the .got section is must
88 if (LinkerConfig::Object != config().codeGenType()) {
89 setGOTSectionSize(pBuilder);
90
91 // set .plt size
92 if (m_pPLT->hasPLT1())
93 m_pPLT->finalizeSectionSize();
94
95 // set .rel.dyn/.rela.dyn size
96 if (!m_pRelDyn->empty()) {
97 assert(!config().isCodeStatic() &&
98 "static linkage should not result in a dynamic relocation section");
99 setRelDynSize();
100 }
101 // set .rel.plt/.rela.plt size
102 if (!m_pRelPLT->empty()) {
103 assert(!config().isCodeStatic() &&
104 "static linkage should not result in a dynamic relocation section");
105 setRelPLTSize();
106 }
107 }
108 }
109
doPostLayout(Module & pModule,IRBuilder & pBuilder)110 void X86GNULDBackend::doPostLayout(Module& pModule,
111 IRBuilder& pBuilder)
112 {
113 }
114
115 /// dynamic - the dynamic section of the target machine.
116 /// Use co-variant return type to return its own dynamic section.
dynamic()117 X86ELFDynamic& X86GNULDBackend::dynamic()
118 {
119 assert(NULL != m_pDynamic);
120 return *m_pDynamic;
121 }
122
123 /// dynamic - the dynamic section of the target machine.
124 /// Use co-variant return type to return its own dynamic section.
dynamic() const125 const X86ELFDynamic& X86GNULDBackend::dynamic() const
126 {
127 assert(NULL != m_pDynamic);
128 return *m_pDynamic;
129 }
130
defineGOTSymbol(IRBuilder & pBuilder,Fragment & pFrag)131 void X86GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder,
132 Fragment& pFrag)
133 {
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 }
146 else {
147 m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
148 "_GLOBAL_OFFSET_TABLE_",
149 ResolveInfo::Object,
150 ResolveInfo::Define,
151 ResolveInfo::Local,
152 0x0, // size
153 0x0, // value
154 FragmentRef::Create(pFrag, 0x0),
155 ResolveInfo::Hidden);
156 }
157 }
158
emitSectionData(const LDSection & pSection,MemoryRegion & pRegion) const159 uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
160 MemoryRegion& pRegion) const
161 {
162 assert(pRegion.size() && "Size of MemoryRegion is zero!");
163
164 const ELFFileFormat* FileFormat = getOutputFormat();
165 assert(FileFormat &&
166 "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
167
168 unsigned int EntrySize = 0;
169 uint64_t RegionSize = 0;
170
171 if (&pSection == &(FileFormat->getPLT())) {
172 assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
173
174 unsigned char* buffer = pRegion.getBuffer();
175
176 m_pPLT->applyPLT0();
177 m_pPLT->applyPLT1();
178 X86PLT::iterator it = m_pPLT->begin();
179 unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size();
180
181 memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size);
182 RegionSize += plt0_size;
183 ++it;
184
185 PLTEntryBase* plt1 = 0;
186 X86PLT::iterator ie = m_pPLT->end();
187 while (it != ie) {
188 plt1 = &(llvm::cast<PLTEntryBase>(*it));
189 EntrySize = plt1->size();
190 memcpy(buffer + RegionSize, plt1->getValue(), EntrySize);
191 RegionSize += EntrySize;
192 ++it;
193 }
194 }
195
196 else if (&pSection == &(FileFormat->getGOT())) {
197 RegionSize += emitGOTSectionData(pRegion);
198 }
199
200 else if (&pSection == &(FileFormat->getGOTPLT())) {
201 RegionSize += emitGOTPLTSectionData(pRegion, FileFormat);
202 }
203
204 else {
205 fatal(diag::unrecognized_output_sectoin)
206 << pSection.name()
207 << "mclinker@googlegroups.com";
208 }
209 return RegionSize;
210 }
211
getPLT()212 X86PLT& X86GNULDBackend::getPLT()
213 {
214 assert(NULL != m_pPLT && "PLT section not exist");
215 return *m_pPLT;
216 }
217
getPLT() const218 const X86PLT& X86GNULDBackend::getPLT() const
219 {
220 assert(NULL != m_pPLT && "PLT section not exist");
221 return *m_pPLT;
222 }
223
getRelDyn()224 OutputRelocSection& X86GNULDBackend::getRelDyn()
225 {
226 assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist");
227 return *m_pRelDyn;
228 }
229
getRelDyn() const230 const OutputRelocSection& X86GNULDBackend::getRelDyn() const
231 {
232 assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist");
233 return *m_pRelDyn;
234 }
235
getRelPLT()236 OutputRelocSection& X86GNULDBackend::getRelPLT()
237 {
238 assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist");
239 return *m_pRelPLT;
240 }
241
getRelPLT() const242 const OutputRelocSection& X86GNULDBackend::getRelPLT() const
243 {
244 assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist");
245 return *m_pRelPLT;
246 }
247
248 unsigned int
getTargetSectionOrder(const LDSection & pSectHdr) const249 X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
250 {
251 const ELFFileFormat* file_format = getOutputFormat();
252
253 if (&pSectHdr == &file_format->getGOT()) {
254 if (config().options().hasNow())
255 return SHO_RELRO;
256 return SHO_RELRO_LAST;
257 }
258
259 if (&pSectHdr == &file_format->getGOTPLT()) {
260 if (config().options().hasNow())
261 return SHO_RELRO;
262 return SHO_NON_RELRO_FIRST;
263 }
264
265 if (&pSectHdr == &file_format->getPLT())
266 return SHO_PLT;
267
268 return SHO_UNDEFINED;
269 }
270
initTargetSymbols(IRBuilder & pBuilder,Module & pModule)271 void X86GNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
272 {
273 if (LinkerConfig::Object != config().codeGenType()) {
274 // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
275 // same name in input
276 m_pGOTSymbol =
277 pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
278 "_GLOBAL_OFFSET_TABLE_",
279 ResolveInfo::Object,
280 ResolveInfo::Define,
281 ResolveInfo::Local,
282 0x0, // size
283 0x0, // value
284 FragmentRef::Null(), // FragRef
285 ResolveInfo::Hidden);
286 }
287 }
288
289 /// finalizeSymbol - finalize the symbol value
finalizeTargetSymbols()290 bool X86GNULDBackend::finalizeTargetSymbols()
291 {
292 return true;
293 }
294
295 /// doCreateProgramHdrs - backend can implement this function to create the
296 /// target-dependent segments
doCreateProgramHdrs(Module & pModule)297 void X86GNULDBackend::doCreateProgramHdrs(Module& pModule)
298 {
299 // TODO
300 }
301
X86_32GNULDBackend(const LinkerConfig & pConfig,GNUInfo * pInfo)302 X86_32GNULDBackend::X86_32GNULDBackend(const LinkerConfig& pConfig,
303 GNUInfo* pInfo)
304 : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_386_COPY),
305 m_pGOT (NULL),
306 m_pGOTPLT (NULL) {
307 }
308
~X86_32GNULDBackend()309 X86_32GNULDBackend::~X86_32GNULDBackend()
310 {
311 delete m_pGOT;
312 delete m_pGOTPLT;
313 }
314
initRelocator()315 bool X86_32GNULDBackend::initRelocator()
316 {
317 if (NULL == m_pRelocator) {
318 m_pRelocator = new X86_32Relocator(*this, config());
319 }
320 return true;
321 }
322
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)323 void X86_32GNULDBackend::initTargetSections(Module& pModule,
324 ObjectBuilder& pBuilder)
325 {
326 if (LinkerConfig::Object != config().codeGenType()) {
327 ELFFileFormat* file_format = getOutputFormat();
328 // initialize .got
329 LDSection& got = file_format->getGOT();
330 m_pGOT = new X86_32GOT(got);
331
332 // initialize .got.plt
333 LDSection& gotplt = file_format->getGOTPLT();
334 m_pGOTPLT = new X86_32GOTPLT(gotplt);
335
336 // initialize .plt
337 LDSection& plt = file_format->getPLT();
338 m_pPLT = new X86_32PLT(plt,
339 *m_pGOTPLT,
340 config());
341
342 // initialize .rel.plt
343 LDSection& relplt = file_format->getRelPlt();
344 relplt.setLink(&plt);
345 m_pRelPLT = new OutputRelocSection(pModule, relplt);
346
347 // initialize .rel.dyn
348 LDSection& reldyn = file_format->getRelDyn();
349 m_pRelDyn = new OutputRelocSection(pModule, reldyn);
350
351 }
352 }
353
getGOT()354 X86_32GOT& X86_32GNULDBackend::getGOT()
355 {
356 assert(NULL != m_pGOT);
357 return *m_pGOT;
358 }
359
getGOT() const360 const X86_32GOT& X86_32GNULDBackend::getGOT() const
361 {
362 assert(NULL != m_pGOT);
363 return *m_pGOT;
364 }
365
getGOTPLT()366 X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT()
367 {
368 assert(NULL != m_pGOTPLT);
369 return *m_pGOTPLT;
370 }
371
getGOTPLT() const372 const X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() const
373 {
374 assert(NULL != m_pGOTPLT);
375 return *m_pGOTPLT;
376 }
377
setRelDynSize()378 void X86_32GNULDBackend::setRelDynSize()
379 {
380 ELFFileFormat* file_format = getOutputFormat();
381 file_format->getRelDyn().setSize
382 (m_pRelDyn->numOfRelocs() * getRelEntrySize());
383 }
384
setRelPLTSize()385 void X86_32GNULDBackend::setRelPLTSize()
386 {
387 ELFFileFormat* file_format = getOutputFormat();
388 file_format->getRelPlt().setSize
389 (m_pRelPLT->numOfRelocs() * getRelEntrySize());
390 }
391
setGOTSectionSize(IRBuilder & pBuilder)392 void X86_32GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder)
393 {
394 // set .got.plt size
395 if (LinkerConfig::DynObj == config().codeGenType() ||
396 m_pGOTPLT->hasGOT1() ||
397 NULL != m_pGOTSymbol) {
398 m_pGOTPLT->finalizeSectionSize();
399 defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin()));
400 }
401
402 // set .got size
403 if (!m_pGOT->empty())
404 m_pGOT->finalizeSectionSize();
405 }
406
emitGOTSectionData(MemoryRegion & pRegion) const407 uint64_t X86_32GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const
408 {
409 assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
410
411 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
412
413 X86_32GOTEntry* got = 0;
414 unsigned int EntrySize = X86_32GOTEntry::EntrySize;
415 uint64_t RegionSize = 0;
416
417 for (X86_32GOT::iterator it = m_pGOT->begin(),
418 ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
419 got = &(llvm::cast<X86_32GOTEntry>((*it)));
420 *buffer = static_cast<uint32_t>(got->getValue());
421 RegionSize += EntrySize;
422 }
423
424 return RegionSize;
425 }
426
emitGOTPLTSectionData(MemoryRegion & pRegion,const ELFFileFormat * FileFormat) const427 uint64_t X86_32GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion,
428 const ELFFileFormat* FileFormat) const
429 {
430 assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!");
431 m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
432 m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
433
434 uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
435
436 X86_32GOTEntry* got = 0;
437 unsigned int EntrySize = X86_32GOTEntry::EntrySize;
438 uint64_t RegionSize = 0;
439
440 for (X86_32GOTPLT::iterator it = m_pGOTPLT->begin(),
441 ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
442 got = &(llvm::cast<X86_32GOTEntry>((*it)));
443 *buffer = static_cast<uint32_t>(got->getValue());
444 RegionSize += EntrySize;
445 }
446
447 return RegionSize;
448 }
449
X86_64GNULDBackend(const LinkerConfig & pConfig,GNUInfo * pInfo)450 X86_64GNULDBackend::X86_64GNULDBackend(const LinkerConfig& pConfig,
451 GNUInfo* pInfo)
452 : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_X86_64_COPY),
453 m_pGOT (NULL),
454 m_pGOTPLT (NULL) {
455 }
456
~X86_64GNULDBackend()457 X86_64GNULDBackend::~X86_64GNULDBackend()
458 {
459 delete m_pGOT;
460 delete m_pGOTPLT;
461 }
462
initRelocator()463 bool X86_64GNULDBackend::initRelocator()
464 {
465 if (NULL == m_pRelocator) {
466 m_pRelocator = new X86_64Relocator(*this, config());
467 }
468 return true;
469 }
470
getGOT()471 X86_64GOT& X86_64GNULDBackend::getGOT()
472 {
473 assert(NULL != m_pGOT);
474 return *m_pGOT;
475 }
476
getGOT() const477 const X86_64GOT& X86_64GNULDBackend::getGOT() const
478 {
479 assert(NULL != m_pGOT);
480 return *m_pGOT;
481 }
482
getGOTPLT()483 X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT()
484 {
485 assert(NULL != m_pGOTPLT);
486 return *m_pGOTPLT;
487 }
488
getGOTPLT() const489 const X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() const
490 {
491 assert(NULL != m_pGOTPLT);
492 return *m_pGOTPLT;
493 }
494
setRelDynSize()495 void X86_64GNULDBackend::setRelDynSize()
496 {
497 ELFFileFormat* file_format = getOutputFormat();
498 file_format->getRelaDyn().setSize
499 (m_pRelDyn->numOfRelocs() * getRelaEntrySize());
500 }
501
setRelPLTSize()502 void X86_64GNULDBackend::setRelPLTSize()
503 {
504 ELFFileFormat* file_format = getOutputFormat();
505 file_format->getRelaPlt().setSize
506 (m_pRelPLT->numOfRelocs() * getRelaEntrySize());
507 }
508
initTargetSections(Module & pModule,ObjectBuilder & pBuilder)509 void X86_64GNULDBackend::initTargetSections(Module& pModule,
510 ObjectBuilder& pBuilder)
511 {
512 if (LinkerConfig::Object != config().codeGenType()) {
513 ELFFileFormat* file_format = getOutputFormat();
514 // initialize .got
515 LDSection& got = file_format->getGOT();
516 m_pGOT = new X86_64GOT(got);
517
518 // initialize .got.plt
519 LDSection& gotplt = file_format->getGOTPLT();
520 m_pGOTPLT = new X86_64GOTPLT(gotplt);
521
522 // initialize .plt
523 LDSection& plt = file_format->getPLT();
524 m_pPLT = new X86_64PLT(plt,
525 *m_pGOTPLT,
526 config());
527
528 // initialize .rela.plt
529 LDSection& relplt = file_format->getRelaPlt();
530 relplt.setLink(&plt);
531 m_pRelPLT = new OutputRelocSection(pModule, relplt);
532
533 // initialize .rela.dyn
534 LDSection& reldyn = file_format->getRelaDyn();
535 m_pRelDyn = new OutputRelocSection(pModule, reldyn);
536
537 }
538 }
539
setGOTSectionSize(IRBuilder & pBuilder)540 void X86_64GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder)
541 {
542 // set .got.plt size
543 if (LinkerConfig::DynObj == config().codeGenType() ||
544 m_pGOTPLT->hasGOT1() ||
545 NULL != m_pGOTSymbol) {
546 m_pGOTPLT->finalizeSectionSize();
547 defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin()));
548 }
549
550 // set .got size
551 if (!m_pGOT->empty())
552 m_pGOT->finalizeSectionSize();
553 }
554
emitGOTSectionData(MemoryRegion & pRegion) const555 uint64_t X86_64GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const
556 {
557 assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
558
559 uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer());
560
561 X86_64GOTEntry* got = 0;
562 unsigned int EntrySize = X86_64GOTEntry::EntrySize;
563 uint64_t RegionSize = 0;
564
565 for (X86_64GOT::iterator it = m_pGOT->begin(),
566 ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
567 got = &(llvm::cast<X86_64GOTEntry>((*it)));
568 *buffer = static_cast<uint64_t>(got->getValue());
569 RegionSize += EntrySize;
570 }
571
572 return RegionSize;
573 }
574
emitGOTPLTSectionData(MemoryRegion & pRegion,const ELFFileFormat * FileFormat) const575 uint64_t X86_64GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion,
576 const ELFFileFormat* FileFormat) const
577 {
578 assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!");
579 m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
580 m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
581
582 uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer());
583
584 X86_64GOTEntry* got = 0;
585 unsigned int EntrySize = X86_64GOTEntry::EntrySize;
586 uint64_t RegionSize = 0;
587
588 for (X86_64GOTPLT::iterator it = m_pGOTPLT->begin(),
589 ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
590 got = &(llvm::cast<X86_64GOTEntry>((*it)));
591 *buffer = static_cast<uint64_t>(got->getValue());
592 RegionSize += EntrySize;
593 }
594
595 return RegionSize;
596 }
597
598 namespace mcld {
599
600 //===----------------------------------------------------------------------===//
601 /// createX86LDBackend - the help funtion to create corresponding X86LDBackend
602 ///
createX86LDBackend(const llvm::Target & pTarget,const LinkerConfig & pConfig)603 TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget,
604 const LinkerConfig& pConfig)
605 {
606 if (pConfig.targets().triple().isOSDarwin()) {
607 assert(0 && "MachO linker is not supported yet");
608 /**
609 return new X86MachOLDBackend(createX86MachOArchiveReader,
610 createX86MachOObjectReader,
611 createX86MachOObjectWriter);
612 **/
613 }
614 if (pConfig.targets().triple().isOSWindows()) {
615 assert(0 && "COFF linker is not supported yet");
616 /**
617 return new X86COFFLDBackend(createX86COFFArchiveReader,
618 createX86COFFObjectReader,
619 createX86COFFObjectWriter);
620 **/
621 }
622 Triple::ArchType arch = pConfig.targets().triple().getArch();
623 if (arch == Triple::x86)
624 return new X86_32GNULDBackend(pConfig,
625 new X86_32GNUInfo(pConfig.targets().triple()));
626 assert (arch == Triple::x86_64);
627 return new X86_64GNULDBackend(pConfig,
628 new X86_64GNUInfo(pConfig.targets().triple()));
629 }
630
631 } // namespace of mcld
632
633 //===----------------------------------------------------------------------===//
634 // Force static initialization.
635 //===----------------------------------------------------------------------===//
MCLDInitializeX86LDBackend()636 extern "C" void MCLDInitializeX86LDBackend() {
637 // Register the linker backend
638 mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_32Target, createX86LDBackend);
639 mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_64Target, createX86LDBackend);
640 }
641