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