1 //===- ELFObjectWriter.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 <mcld/LD/ELFObjectWriter.h>
10
11 #include <mcld/Module.h>
12 #include <mcld/LinkerConfig.h>
13 #include <mcld/Target/GNULDBackend.h>
14 #include <mcld/Support/MemoryArea.h>
15 #include <mcld/Support/MemoryRegion.h>
16 #include <mcld/Support/MsgHandling.h>
17 #include <mcld/ADT/SizeTraits.h>
18 #include <mcld/Fragment/FragmentLinker.h>
19 #include <mcld/Fragment/AlignFragment.h>
20 #include <mcld/Fragment/FillFragment.h>
21 #include <mcld/Fragment/RegionFragment.h>
22 #include <mcld/Fragment/Stub.h>
23 #include <mcld/Fragment/NullFragment.h>
24 #include <mcld/LD/LDSection.h>
25 #include <mcld/LD/SectionData.h>
26 #include <mcld/LD/ELFSegment.h>
27 #include <mcld/LD/ELFSegmentFactory.h>
28 #include <mcld/LD/RelocData.h>
29 #include <mcld/LD/EhFrame.h>
30
31 #include <llvm/Support/ErrorHandling.h>
32 #include <llvm/Support/system_error.h>
33 #include <llvm/Support/ELF.h>
34 #include <llvm/Support/Casting.h>
35
36 using namespace llvm;
37 using namespace llvm::ELF;
38 using namespace mcld;
39
40 //===----------------------------------------------------------------------===//
41 // ELFObjectWriter
42 //===----------------------------------------------------------------------===//
ELFObjectWriter(GNULDBackend & pBackend,const LinkerConfig & pConfig)43 ELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend,
44 const LinkerConfig& pConfig)
45 : ObjectWriter(), m_Backend(pBackend), m_Config(pConfig)
46 {
47 }
48
~ELFObjectWriter()49 ELFObjectWriter::~ELFObjectWriter()
50 {
51 }
52
writeSection(MemoryArea & pOutput,LDSection * section)53 void ELFObjectWriter::writeSection(MemoryArea& pOutput, LDSection *section)
54 {
55 MemoryRegion* region;
56 // Request output region
57 switch (section->kind()) {
58 case LDFileFormat::Note:
59 if (section->getSectionData() == NULL)
60 return;
61 // Fall through
62 case LDFileFormat::Regular:
63 case LDFileFormat::Relocation:
64 case LDFileFormat::Target:
65 case LDFileFormat::Debug:
66 case LDFileFormat::GCCExceptTable:
67 case LDFileFormat::EhFrame: {
68 region = pOutput.request(section->offset(), section->size());
69 if (NULL == region) {
70 llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
71 llvm::Twine(section->name()) +
72 llvm::Twine("'.\n"));
73 }
74 break;
75 }
76 case LDFileFormat::Null:
77 case LDFileFormat::NamePool:
78 case LDFileFormat::BSS:
79 case LDFileFormat::MetaData:
80 case LDFileFormat::Version:
81 case LDFileFormat::EhFrameHdr:
82 case LDFileFormat::StackNote:
83 // Ignore these sections
84 return;
85 default:
86 llvm::errs() << "WARNING: unsupported section kind: "
87 << section->kind()
88 << " of section "
89 << section->name()
90 << ".\n";
91 return;
92 }
93
94 // Write out sections with data
95 switch(section->kind()) {
96 case LDFileFormat::GCCExceptTable:
97 case LDFileFormat::EhFrame:
98 case LDFileFormat::Regular:
99 case LDFileFormat::Debug:
100 case LDFileFormat::Note:
101 // FIXME: if optimization of exception handling sections is enabled,
102 // then we should emit these sections by the other way.
103 emitSectionData(*section, *region);
104 break;
105 case LDFileFormat::Relocation:
106 emitRelocation(m_Config, *section, *region);
107 break;
108 case LDFileFormat::Target:
109 target().emitSectionData(*section, *region);
110 break;
111 default:
112 llvm_unreachable("invalid section kind");
113 }
114 }
115
writeObject(Module & pModule,MemoryArea & pOutput)116 llvm::error_code ELFObjectWriter::writeObject(Module& pModule,
117 MemoryArea& pOutput)
118 {
119 bool is_dynobj = m_Config.codeGenType() == LinkerConfig::DynObj;
120 bool is_exec = m_Config.codeGenType() == LinkerConfig::Exec;
121 bool is_binary = m_Config.codeGenType() == LinkerConfig::Binary;
122 bool is_object = m_Config.codeGenType() == LinkerConfig::Object;
123
124 assert(is_dynobj || is_exec || is_binary || is_object);
125
126 if (is_dynobj || is_exec) {
127 // Allow backend to sort symbols before emitting
128 target().orderSymbolTable(pModule);
129
130 // Write out the interpreter section: .interp
131 target().emitInterp(pOutput);
132
133 // Write out name pool sections: .dynsym, .dynstr, .hash
134 target().emitDynNamePools(pModule, pOutput);
135 }
136
137 if (is_object || is_dynobj || is_exec) {
138 // Write out name pool sections: .symtab, .strtab
139 target().emitRegNamePools(pModule, pOutput);
140 }
141
142 if (is_binary) {
143 // Iterate over the loadable segments and write the corresponding sections
144 ELFSegmentFactory::iterator seg, segEnd = target().elfSegmentTable().end();
145
146 for (seg = target().elfSegmentTable().begin(); seg != segEnd; ++seg) {
147 if (llvm::ELF::PT_LOAD == (*seg).type()) {
148 ELFSegment::sect_iterator sect, sectEnd = (*seg).end();
149 for (sect = (*seg).begin(); sect != sectEnd; ++sect)
150 writeSection(pOutput, *sect);
151 }
152 }
153 } else {
154 // Write out regular ELF sections
155 Module::iterator sect, sectEnd = pModule.end();
156 for (sect = pModule.begin(); sect != sectEnd; ++sect)
157 writeSection(pOutput, *sect);
158
159 emitShStrTab(target().getOutputFormat()->getShStrTab(), pModule, pOutput);
160
161 if (m_Config.targets().is32Bits()) {
162 // Write out ELF header
163 // Write out section header table
164 writeELFHeader<32>(m_Config, pModule, pOutput);
165 if (is_dynobj || is_exec)
166 emitProgramHeader<32>(pOutput);
167
168 emitSectionHeader<32>(pModule, m_Config, pOutput);
169 }
170 else if (m_Config.targets().is64Bits()) {
171 // Write out ELF header
172 // Write out section header table
173 writeELFHeader<64>(m_Config, pModule, pOutput);
174 if (is_dynobj || is_exec)
175 emitProgramHeader<64>(pOutput);
176
177 emitSectionHeader<64>(pModule, m_Config, pOutput);
178 }
179 else
180 return make_error_code(errc::not_supported);
181 }
182
183 pOutput.clear();
184 return llvm::make_error_code(llvm::errc::success);
185 }
186
187 // writeELFHeader - emit ElfXX_Ehdr
188 template<size_t SIZE>
writeELFHeader(const LinkerConfig & pConfig,const Module & pModule,MemoryArea & pOutput) const189 void ELFObjectWriter::writeELFHeader(const LinkerConfig& pConfig,
190 const Module& pModule,
191 MemoryArea& pOutput) const
192 {
193 typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
194 typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;
195 typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;
196
197 // ELF header must start from 0x0
198 MemoryRegion *region = pOutput.request(0, sizeof(ElfXX_Ehdr));
199 ElfXX_Ehdr* header = (ElfXX_Ehdr*)region->start();
200
201 memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
202
203 header->e_ident[EI_CLASS] = (SIZE == 32) ? ELFCLASS32 : ELFCLASS64;
204 header->e_ident[EI_DATA] = pConfig.targets().isLittleEndian()?
205 ELFDATA2LSB : ELFDATA2MSB;
206 header->e_ident[EI_VERSION] = target().getInfo().ELFVersion();
207 header->e_ident[EI_OSABI] = target().getInfo().OSABI();
208 header->e_ident[EI_ABIVERSION] = target().getInfo().ABIVersion();
209
210 // FIXME: add processor-specific and core file types.
211 switch(pConfig.codeGenType()) {
212 case LinkerConfig::Object:
213 header->e_type = ET_REL;
214 break;
215 case LinkerConfig::DynObj:
216 header->e_type = ET_DYN;
217 break;
218 case LinkerConfig::Exec:
219 header->e_type = ET_EXEC;
220 break;
221 default:
222 llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
223 header->e_type = ET_NONE;
224 }
225 header->e_machine = target().getInfo().machine();
226 header->e_version = header->e_ident[EI_VERSION];
227 header->e_entry = getEntryPoint(pConfig, pModule);
228
229 if (LinkerConfig::Object != pConfig.codeGenType())
230 header->e_phoff = sizeof(ElfXX_Ehdr);
231 else
232 header->e_phoff = 0x0;
233
234 header->e_shoff = getLastStartOffset<SIZE>(pModule);
235 header->e_flags = target().getInfo().flags();
236 header->e_ehsize = sizeof(ElfXX_Ehdr);
237 header->e_phentsize = sizeof(ElfXX_Phdr);
238 header->e_phnum = target().numOfSegments();
239 header->e_shentsize = sizeof(ElfXX_Shdr);
240 header->e_shnum = pModule.size();
241 header->e_shstrndx = pModule.getSection(".shstrtab")->index();
242 }
243
244 /// getEntryPoint
getEntryPoint(const LinkerConfig & pConfig,const Module & pModule) const245 uint64_t ELFObjectWriter::getEntryPoint(const LinkerConfig& pConfig,
246 const Module& pModule) const
247 {
248 llvm::StringRef entry_name;
249 if (pConfig.options().hasEntry())
250 entry_name = pConfig.options().entry();
251 else
252 entry_name = target().getInfo().entry();
253
254 uint64_t result = 0x0;
255
256 bool issue_warning = (pConfig.options().hasEntry() &&
257 LinkerConfig::Object != pConfig.codeGenType() &&
258 LinkerConfig::DynObj != pConfig.codeGenType());
259
260 const LDSymbol* entry_symbol = pModule.getNamePool().findSymbol(entry_name);
261
262 // found the symbol
263 if (NULL != entry_symbol) {
264 if (entry_symbol->desc() != ResolveInfo::Define && issue_warning) {
265 llvm::errs() << "WARNING: entry symbol '"
266 << entry_symbol->name()
267 << "' exists but is not defined.\n";
268 }
269 result = entry_symbol->value();
270 }
271 // not in the symbol pool
272 else {
273 // We should parse entry as a number.
274 // @ref GNU ld manual, Options -e. e.g., -e 0x1000.
275 char* endptr;
276 result = strtoull(entry_name.data(), &endptr, 0);
277 if (*endptr != '\0') {
278 if (issue_warning) {
279 llvm::errs() << "cannot find entry symbol '"
280 << entry_name.data()
281 << "'.\n";
282 }
283 result = 0x0;
284 }
285 }
286 return result;
287 }
288
289 // emitSectionHeader - emit ElfXX_Shdr
290 template<size_t SIZE>
emitSectionHeader(const Module & pModule,const LinkerConfig & pConfig,MemoryArea & pOutput) const291 void ELFObjectWriter::emitSectionHeader(const Module& pModule,
292 const LinkerConfig& pConfig,
293 MemoryArea& pOutput) const
294 {
295 typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;
296
297 // emit section header
298 unsigned int sectNum = pModule.size();
299 unsigned int header_size = sizeof(ElfXX_Shdr) * sectNum;
300 MemoryRegion* region = pOutput.request(getLastStartOffset<SIZE>(pModule),
301 header_size);
302 ElfXX_Shdr* shdr = (ElfXX_Shdr*)region->start();
303
304 // Iterate the SectionTable in LDContext
305 unsigned int sectIdx = 0;
306 unsigned int shstridx = 0; // NULL section has empty name
307 for (; sectIdx < sectNum; ++sectIdx) {
308 const LDSection *ld_sect = pModule.getSectionTable().at(sectIdx);
309 shdr[sectIdx].sh_name = shstridx;
310 shdr[sectIdx].sh_type = ld_sect->type();
311 shdr[sectIdx].sh_flags = ld_sect->flag();
312 shdr[sectIdx].sh_addr = ld_sect->addr();
313 shdr[sectIdx].sh_offset = ld_sect->offset();
314 shdr[sectIdx].sh_size = ld_sect->size();
315 shdr[sectIdx].sh_addralign = ld_sect->align();
316 shdr[sectIdx].sh_entsize = getSectEntrySize<SIZE>(*ld_sect);
317 shdr[sectIdx].sh_link = getSectLink(*ld_sect, pConfig);
318 shdr[sectIdx].sh_info = getSectInfo(*ld_sect);
319
320 // adjust strshidx
321 shstridx += ld_sect->name().size() + 1;
322 }
323 }
324
325 // emitProgramHeader - emit ElfXX_Phdr
326 template<size_t SIZE>
emitProgramHeader(MemoryArea & pOutput) const327 void ELFObjectWriter::emitProgramHeader(MemoryArea& pOutput) const
328 {
329 typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
330 typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;
331
332 uint64_t start_offset, phdr_size;
333
334 start_offset = sizeof(ElfXX_Ehdr);
335 phdr_size = sizeof(ElfXX_Phdr);
336 // Program header must start directly after ELF header
337 MemoryRegion *region = pOutput.request(start_offset,
338 target().numOfSegments() * phdr_size);
339
340 ElfXX_Phdr* phdr = (ElfXX_Phdr*)region->start();
341
342 // Iterate the elf segment table in GNULDBackend
343 size_t index = 0;
344 ELFSegmentFactory::const_iterator seg = target().elfSegmentTable().begin(),
345 segEnd = target().elfSegmentTable().end();
346 for (; seg != segEnd; ++seg, ++index) {
347 phdr[index].p_type = (*seg).type();
348 phdr[index].p_flags = (*seg).flag();
349 phdr[index].p_offset = (*seg).offset();
350 phdr[index].p_vaddr = (*seg).vaddr();
351 phdr[index].p_paddr = (*seg).paddr();
352 phdr[index].p_filesz = (*seg).filesz();
353 phdr[index].p_memsz = (*seg).memsz();
354 phdr[index].p_align = (*seg).align();
355 }
356 }
357
358 /// emitShStrTab - emit section string table
359 void
emitShStrTab(const LDSection & pShStrTab,const Module & pModule,MemoryArea & pOutput)360 ELFObjectWriter::emitShStrTab(const LDSection& pShStrTab,
361 const Module& pModule,
362 MemoryArea& pOutput)
363 {
364 // write out data
365 MemoryRegion* region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
366 unsigned char* data = region->start();
367 size_t shstrsize = 0;
368 Module::const_iterator section, sectEnd = pModule.end();
369 for (section = pModule.begin(); section != sectEnd; ++section) {
370 strcpy((char*)(data + shstrsize), (*section)->name().data());
371 shstrsize += (*section)->name().size() + 1;
372 }
373 }
374
375 /// emitSectionData
376 void
emitSectionData(const LDSection & pSection,MemoryRegion & pRegion) const377 ELFObjectWriter::emitSectionData(const LDSection& pSection,
378 MemoryRegion& pRegion) const
379 {
380 const SectionData* sd = NULL;
381 switch (pSection.kind()) {
382 case LDFileFormat::Relocation:
383 assert(pSection.hasRelocData());
384 return;
385 case LDFileFormat::EhFrame:
386 assert(pSection.hasEhFrame());
387 sd = pSection.getEhFrame()->getSectionData();
388 break;
389 default:
390 assert(pSection.hasSectionData());
391 sd = pSection.getSectionData();
392 break;
393 }
394 emitSectionData(*sd, pRegion);
395 }
396
397 /// emitRelocation
emitRelocation(const LinkerConfig & pConfig,const LDSection & pSection,MemoryRegion & pRegion) const398 void ELFObjectWriter::emitRelocation(const LinkerConfig& pConfig,
399 const LDSection& pSection,
400 MemoryRegion& pRegion) const
401 {
402 const RelocData* sect_data = pSection.getRelocData();
403 assert(NULL != sect_data && "SectionData is NULL in emitRelocation!");
404
405 if (pSection.type() == SHT_REL) {
406 if (pConfig.targets().is32Bits())
407 emitRel<32>(pConfig, *sect_data, pRegion);
408 else if (pConfig.targets().is64Bits())
409 emitRel<64>(pConfig, *sect_data, pRegion);
410 else {
411 fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str()
412 << pConfig.targets().bitclass();
413 }
414 } else if (pSection.type() == SHT_RELA) {
415 if (pConfig.targets().is32Bits())
416 emitRela<32>(pConfig, *sect_data, pRegion);
417 else if (pConfig.targets().is64Bits())
418 emitRela<64>(pConfig, *sect_data, pRegion);
419 else {
420 fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str()
421 << pConfig.targets().bitclass();
422 }
423 } else
424 llvm::report_fatal_error("unsupported relocation section type!");
425 }
426
427
428 // emitRel - emit ElfXX_Rel
429 template<size_t SIZE>
emitRel(const LinkerConfig & pConfig,const RelocData & pRelocData,MemoryRegion & pRegion) const430 void ELFObjectWriter::emitRel(const LinkerConfig& pConfig,
431 const RelocData& pRelocData,
432 MemoryRegion& pRegion) const
433 {
434 typedef typename ELFSizeTraits<SIZE>::Rel ElfXX_Rel;
435 typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
436 typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
437
438 ElfXX_Rel* rel = reinterpret_cast<ElfXX_Rel*>(pRegion.start());
439
440 const Relocation* relocation = 0;
441 const FragmentRef* frag_ref = 0;
442
443 for (RelocData::const_iterator it = pRelocData.begin(),
444 ie = pRelocData.end(); it != ie; ++it, ++rel) {
445
446 relocation = &(llvm::cast<Relocation>(*it));
447 frag_ref = &(relocation->targetRef());
448
449 if(LinkerConfig::DynObj == pConfig.codeGenType() ||
450 LinkerConfig::Exec == pConfig.codeGenType()) {
451 rel->r_offset = static_cast<ElfXX_Addr>(
452 frag_ref->frag()->getParent()->getSection().addr() +
453 frag_ref->getOutputOffset());
454 }
455 else {
456 rel->r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
457 }
458 ElfXX_Word Index;
459 if( relocation->symInfo() == NULL )
460 Index = 0;
461 else
462 Index = static_cast<ElfXX_Word>(
463 target().getSymbolIdx(relocation->symInfo()->outSymbol()));
464
465 rel->setSymbolAndType(Index, relocation->type());
466 }
467 }
468
469 // emitRela - emit ElfXX_Rela
470 template<size_t SIZE>
emitRela(const LinkerConfig & pConfig,const RelocData & pRelocData,MemoryRegion & pRegion) const471 void ELFObjectWriter::emitRela(const LinkerConfig& pConfig,
472 const RelocData& pRelocData,
473 MemoryRegion& pRegion) const
474 {
475 typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela;
476 typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
477 typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
478
479 ElfXX_Rela* rel = reinterpret_cast<ElfXX_Rela*>(pRegion.start());
480
481 const Relocation* relocation = 0;
482 const FragmentRef* frag_ref = 0;
483
484 for (RelocData::const_iterator it = pRelocData.begin(),
485 ie = pRelocData.end(); it != ie; ++it, ++rel) {
486
487 relocation = &(llvm::cast<Relocation>(*it));
488 frag_ref = &(relocation->targetRef());
489
490 if(LinkerConfig::DynObj == pConfig.codeGenType() ||
491 LinkerConfig::Exec == pConfig.codeGenType()) {
492 rel->r_offset = static_cast<ElfXX_Addr>(
493 frag_ref->frag()->getParent()->getSection().addr() +
494 frag_ref->getOutputOffset());
495 }
496 else {
497 rel->r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
498 }
499
500 ElfXX_Word Index;
501 if( relocation->symInfo() == NULL )
502 Index = 0;
503 else
504 Index = static_cast<ElfXX_Word>(
505 target().getSymbolIdx(relocation->symInfo()->outSymbol()));
506
507 rel->setSymbolAndType(Index, relocation->type());
508 rel->r_addend = relocation->addend();
509 }
510 }
511
512
513 /// getSectEntrySize - compute ElfXX_Shdr::sh_entsize
514 template<size_t SIZE>
getSectEntrySize(const LDSection & pSection) const515 uint64_t ELFObjectWriter::getSectEntrySize(const LDSection& pSection) const
516 {
517 typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
518 typedef typename ELFSizeTraits<SIZE>::Sym ElfXX_Sym;
519 typedef typename ELFSizeTraits<SIZE>::Rel ElfXX_Rel;
520 typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela;
521 typedef typename ELFSizeTraits<SIZE>::Dyn ElfXX_Dyn;
522
523 if (llvm::ELF::SHT_DYNSYM == pSection.type() ||
524 llvm::ELF::SHT_SYMTAB == pSection.type())
525 return sizeof(ElfXX_Sym);
526 if (llvm::ELF::SHT_REL == pSection.type())
527 return sizeof(ElfXX_Rel);
528 if (llvm::ELF::SHT_RELA == pSection.type())
529 return sizeof(ElfXX_Rela);
530 if (llvm::ELF::SHT_HASH == pSection.type() ||
531 llvm::ELF::SHT_GNU_HASH == pSection.type())
532 return sizeof(ElfXX_Word);
533 if (llvm::ELF::SHT_DYNAMIC == pSection.type())
534 return sizeof(ElfXX_Dyn);
535 return 0x0;
536 }
537
538 /// getSectLink - compute ElfXX_Shdr::sh_link
getSectLink(const LDSection & pSection,const LinkerConfig & pConfig) const539 uint64_t ELFObjectWriter::getSectLink(const LDSection& pSection,
540 const LinkerConfig& pConfig) const
541 {
542 if (llvm::ELF::SHT_SYMTAB == pSection.type())
543 return target().getOutputFormat()->getStrTab().index();
544 if (llvm::ELF::SHT_DYNSYM == pSection.type())
545 return target().getOutputFormat()->getDynStrTab().index();
546 if (llvm::ELF::SHT_DYNAMIC == pSection.type())
547 return target().getOutputFormat()->getDynStrTab().index();
548 if (llvm::ELF::SHT_HASH == pSection.type() ||
549 llvm::ELF::SHT_GNU_HASH == pSection.type())
550 return target().getOutputFormat()->getDynSymTab().index();
551 if (llvm::ELF::SHT_REL == pSection.type() ||
552 llvm::ELF::SHT_RELA == pSection.type()) {
553 if (LinkerConfig::Object == pConfig.codeGenType())
554 return target().getOutputFormat()->getSymTab().index();
555 else
556 return target().getOutputFormat()->getDynSymTab().index();
557 }
558 // FIXME: currently we link ARM_EXIDX section to output text section here
559 if (llvm::ELF::SHT_ARM_EXIDX == pSection.type())
560 return target().getOutputFormat()->getText().index();
561 return llvm::ELF::SHN_UNDEF;
562 }
563
564 /// getSectInfo - compute ElfXX_Shdr::sh_info
getSectInfo(const LDSection & pSection) const565 uint64_t ELFObjectWriter::getSectInfo(const LDSection& pSection) const
566 {
567 if (llvm::ELF::SHT_SYMTAB == pSection.type() ||
568 llvm::ELF::SHT_DYNSYM == pSection.type())
569 return pSection.getInfo();
570
571 if (llvm::ELF::SHT_REL == pSection.type() ||
572 llvm::ELF::SHT_RELA == pSection.type()) {
573 const LDSection* info_link = pSection.getLink();
574 if (NULL != info_link)
575 return info_link->index();
576 }
577
578 return 0x0;
579 }
580
581 /// getLastStartOffset
582 template<>
getLastStartOffset(const Module & pModule) const583 uint64_t ELFObjectWriter::getLastStartOffset<32>(const Module& pModule) const
584 {
585 const LDSection* lastSect = pModule.back();
586 assert(lastSect != NULL);
587 return Align<32>(lastSect->offset() + lastSect->size());
588 }
589
590 /// getLastStartOffset
591 template<>
getLastStartOffset(const Module & pModule) const592 uint64_t ELFObjectWriter::getLastStartOffset<64>(const Module& pModule) const
593 {
594 const LDSection* lastSect = pModule.back();
595 assert(lastSect != NULL);
596 return Align<64>(lastSect->offset() + lastSect->size());
597 }
598
599 /// emitSectionData
emitSectionData(const SectionData & pSD,MemoryRegion & pRegion) const600 void ELFObjectWriter::emitSectionData(const SectionData& pSD,
601 MemoryRegion& pRegion) const
602 {
603 SectionData::const_iterator fragIter, fragEnd = pSD.end();
604 size_t cur_offset = 0;
605 for (fragIter = pSD.begin(); fragIter != fragEnd; ++fragIter) {
606 size_t size = fragIter->size();
607 switch(fragIter->getKind()) {
608 case Fragment::Region: {
609 const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
610 const uint8_t* from = region_frag.getRegion().start();
611 memcpy(pRegion.getBuffer(cur_offset), from, size);
612 break;
613 }
614 case Fragment::Alignment: {
615 // TODO: emit values with different sizes (> 1 byte), and emit nops
616 const AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
617 uint64_t count = size / align_frag.getValueSize();
618 switch (align_frag.getValueSize()) {
619 case 1u:
620 std::memset(pRegion.getBuffer(cur_offset),
621 align_frag.getValue(),
622 count);
623 break;
624 default:
625 llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
626 break;
627 }
628 break;
629 }
630 case Fragment::Fillment: {
631 const FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
632 if (0 == size ||
633 0 == fill_frag.getValueSize() ||
634 0 == fill_frag.size()) {
635 // ignore virtual fillment
636 break;
637 }
638
639 uint64_t num_tiles = fill_frag.size() / fill_frag.getValueSize();
640 for (uint64_t i = 0; i != num_tiles; ++i) {
641 std::memset(pRegion.getBuffer(cur_offset),
642 fill_frag.getValue(),
643 fill_frag.getValueSize());
644 }
645 break;
646 }
647 case Fragment::Stub: {
648 const Stub& stub_frag = llvm::cast<Stub>(*fragIter);
649 memcpy(pRegion.getBuffer(cur_offset), stub_frag.getContent(), size);
650 break;
651 }
652 case Fragment::Null: {
653 assert(0x0 == size);
654 break;
655 }
656 case Fragment::Target:
657 llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
658 break;
659 default:
660 llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
661 break;
662 }
663 cur_offset += size;
664 }
665 }
666
667