ELFObjectWriter.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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
36using namespace llvm;
37using namespace llvm::ELF;
38using namespace mcld;
39
40//===----------------------------------------------------------------------===//
41// ELFObjectWriter
42//===----------------------------------------------------------------------===//
43ELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend,
44                                 const LinkerConfig& pConfig)
45  : ObjectWriter(), m_Backend(pBackend), m_Config(pConfig)
46{
47}
48
49ELFObjectWriter::~ELFObjectWriter()
50{
51}
52
53void 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
116llvm::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    // 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);
148      }
149    }
150  } 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);
155
156    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);
166    }
167    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);
173
174      emitSectionHeader<64>(pModule, m_Config, pOutput);
175    }
176    else
177      return make_error_code(errc::not_supported);
178  }
179
180  pOutput.clear();
181  return llvm::make_error_code(llvm::errc::success);
182}
183
184// 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
664