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