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    // 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
188template<size_t SIZE>
189void 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
245uint64_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
290template<size_t SIZE>
291void 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
326template<size_t SIZE>
327void 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
359void
360ELFObjectWriter::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
376void
377ELFObjectWriter::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
398void 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
429template<size_t SIZE>
430void 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
470template<size_t SIZE>
471void 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
514template<size_t SIZE>
515uint64_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
539uint64_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
565uint64_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
582template<>
583uint64_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
591template<>
592uint64_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
600void 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