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