1//===- ELFWriter.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
10#include <cstdlib>
11#include <cstring>
12
13#include <llvm/Support/ELF.h>
14#include <llvm/Support/Casting.h>
15
16#include <mcld/ADT/SizeTraits.h>
17#include <mcld/MC/MCLDInfo.h>
18#include <mcld/MC/MCLinker.h>
19#include <mcld/LD/AlignFragment.h>
20#include <mcld/LD/FillFragment.h>
21#include <mcld/LD/RegionFragment.h>
22#include <mcld/LD/ELFWriter.h>
23#include <mcld/LD/LDSymbol.h>
24#include <mcld/LD/LDSection.h>
25#include <mcld/LD/Layout.h>
26#include <mcld/LD/ELFSegment.h>
27#include <mcld/LD/ELFSegmentFactory.h>
28#include <mcld/Target/GNULDBackend.h>
29#include <mcld/Support/MemoryRegion.h>
30
31using namespace llvm::ELF;
32using namespace mcld;
33
34/// writeELF32Header - write ELF header
35void ELFWriter::writeELF32Header(const MCLDInfo& pLDInfo,
36                                 const Layout& pLayout,
37                                 const GNULDBackend& pBackend,
38                                 Output& pOutput) const
39{
40    assert(pOutput.hasMemArea());
41
42    // ELF header must start from 0x0
43    MemoryRegion *region = pOutput.memArea()->request(0,
44                                                      sizeof(Elf32_Ehdr));
45    Elf32_Ehdr* header = (Elf32_Ehdr*)region->start();
46
47    memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
48
49    header->e_ident[EI_CLASS]      = ELFCLASS32;
50    header->e_ident[EI_DATA]       = pBackend.isLittleEndian()?
51                                       ELFDATA2LSB : ELFDATA2MSB;
52    header->e_ident[EI_VERSION]    = pBackend.ELFVersion();
53    header->e_ident[EI_OSABI]      = pBackend.OSABI();
54    header->e_ident[EI_ABIVERSION] = pBackend.ABIVersion();
55
56    // FIXME: add processor-specific and core file types.
57    switch(pOutput.type()) {
58    case Output::Object:
59      header->e_type = ET_REL;
60      break;
61    case Output::DynObj:
62      header->e_type = ET_DYN;
63      break;
64    case Output::Exec:
65      header->e_type = ET_EXEC;
66      break;
67    default:
68      llvm::errs() << "unspported output file type: " << pOutput.type() << ".\n";
69      header->e_type = ET_NONE;
70    }
71    header->e_machine   = pBackend.machine();
72    header->e_version   = header->e_ident[EI_VERSION];
73    header->e_entry     = getEntryPoint(pLDInfo, pLayout, pBackend, pOutput);
74    header->e_phoff     = sizeof(Elf32_Ehdr);
75    header->e_shoff     = getELF32LastStartOffset(pOutput);
76    header->e_flags     = pBackend.flags();
77    header->e_ehsize    = sizeof(Elf32_Ehdr);
78    header->e_phentsize = sizeof(Elf32_Phdr);
79    header->e_phnum     = pBackend.numOfSegments();
80    header->e_shentsize = sizeof(Elf32_Shdr);
81    header->e_shnum     = pOutput.context()->numOfSections();
82    header->e_shstrndx  = pOutput.context()->getSectionIdx(".shstrtab");
83}
84
85/// writeELF64Header - write ELF header
86void ELFWriter::writeELF64Header(const MCLDInfo& pLDInfo,
87                                 const Layout& pLayout,
88                                 const GNULDBackend& pBackend,
89                                 Output& pOutput) const
90{
91    assert(pOutput.hasMemArea());
92
93    // ELF header must start from 0x0
94    MemoryRegion *region = pOutput.memArea()->request(0,
95                                                      sizeof(Elf64_Ehdr));
96    Elf64_Ehdr* header = (Elf64_Ehdr*)region->start();
97
98    memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
99
100    header->e_ident[EI_CLASS]      = ELFCLASS64;
101    header->e_ident[EI_DATA]       = pBackend.isLittleEndian()?
102                                       ELFDATA2LSB : ELFDATA2MSB;
103    header->e_ident[EI_VERSION]    = pBackend.ELFVersion();
104    header->e_ident[EI_OSABI]      = pBackend.OSABI();
105    header->e_ident[EI_ABIVERSION] = pBackend.ABIVersion();
106
107    // FIXME: add processor-specific and core file types.
108    switch(pOutput.type()) {
109    case Output::Object:
110      header->e_type = ET_REL;
111      break;
112    case Output::DynObj:
113      header->e_type = ET_DYN;
114      break;
115    case Output::Exec:
116      header->e_type = ET_EXEC;
117      break;
118    default:
119      llvm::errs() << "unspported output file type: " << pOutput.type() << ".\n";
120      header->e_type = ET_NONE;
121    }
122    header->e_machine   = pBackend.machine();
123    header->e_version   = header->e_ident[EI_VERSION];
124    header->e_entry     = getEntryPoint(pLDInfo, pLayout, pBackend, pOutput);
125    header->e_phoff     = sizeof(Elf64_Ehdr);
126    header->e_shoff     = getELF64LastStartOffset(pOutput);
127    header->e_flags     = pBackend.flags();
128    header->e_ehsize    = sizeof(Elf64_Ehdr);
129    header->e_phentsize = sizeof(Elf64_Phdr);
130    header->e_phnum     = pBackend.numOfSegments();
131    header->e_shentsize = sizeof(Elf64_Shdr);
132    header->e_shnum     = pOutput.context()->numOfSections();
133    header->e_shstrndx  = pOutput.context()->getSectionIdx(".shstrtab");
134}
135
136/// getEntryPoint
137uint64_t ELFWriter::getEntryPoint(const MCLDInfo& pLDInfo,
138                                  const Layout& pLayout,
139                                  const GNULDBackend& pBackend,
140                                  const Output& pOutput) const
141{
142
143  llvm::StringRef entry_name;
144  if (pLDInfo.options().hasEntry())
145    entry_name = pLDInfo.options().entry();
146  else
147    entry_name = pBackend.entry();
148
149  uint64_t result = 0x0;
150
151  bool issue_warning = (pLDInfo.options().hasEntry()
152                       && (pOutput.type() != Output::Object)
153                       && (pOutput.type() != Output::DynObj));
154
155  const LDSymbol* entry_symbol = pLDInfo.getNamePool().findSymbol(entry_name);
156
157  // found the symbol
158  if (NULL != entry_symbol) {
159    if (entry_symbol->desc() != ResolveInfo::Define && issue_warning) {
160      llvm::errs() << "WARNING: entry symbol '"
161                   << entry_symbol->name()
162                   << "' exists but is not defined.\n";
163    }
164    result = entry_symbol->value();
165  }
166  // not in the symbol pool
167  else {
168    // We should parse entry as a number.
169    // @ref GNU ld manual, Options -e. e.g., -e 0x1000.
170    char* endptr;
171    result = strtoull(entry_name.data(), &endptr, 0);
172    if (*endptr != '\0') {
173      if (issue_warning) {
174        llvm::errs() << "cannot find entry symbol '"
175                     << entry_name.data()
176                     << "'.\n";
177      }
178      result = 0x0;
179    }
180  }
181  return result;
182}
183
184/// emitELF32SectionHeader - emit Elf32_Shdr
185void
186ELFWriter::emitELF32SectionHeader(Output& pOutput, MCLinker& pLinker) const
187{
188  // emit section header
189  unsigned int sectNum = pOutput.context()->numOfSections();
190  unsigned int header_size = sizeof(Elf32_Shdr) * sectNum;
191  MemoryRegion* region = pOutput.memArea()->request(
192                                   getELF32LastStartOffset(pOutput),
193                                   header_size);
194  Elf32_Shdr* shdr = (Elf32_Shdr*)region->start();
195
196  // Iterate the SectionTable in LDContext
197  unsigned int sectIdx = 0;
198  unsigned int shstridx = 0; // NULL section has empty name
199  for (; sectIdx < sectNum; ++sectIdx) {
200    const LDSection *ld_sect = pOutput.context()->getSection(sectIdx);
201    shdr[sectIdx].sh_name      = shstridx;
202    shdr[sectIdx].sh_type      = ld_sect->type();
203    shdr[sectIdx].sh_flags     = ld_sect->flag();
204    shdr[sectIdx].sh_addr      = ld_sect->addr();
205    shdr[sectIdx].sh_offset    = ld_sect->offset();
206    shdr[sectIdx].sh_size      = ld_sect->size();
207    shdr[sectIdx].sh_addralign = ld_sect->align();
208    shdr[sectIdx].sh_entsize   = getELF32SectEntrySize(*ld_sect);
209    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pOutput);
210    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect, pOutput);
211
212    // adjust strshidx
213    shstridx += ld_sect->name().size() + 1;
214  }
215}
216
217/// emitELF64SectionHeader - emit Elf64_Shdr
218void
219ELFWriter::emitELF64SectionHeader(Output& pOutput, MCLinker& pLinker) const
220{
221  // emit section header
222  unsigned int sectNum = pOutput.context()->numOfSections();
223  unsigned int header_size = sizeof(Elf64_Shdr) * sectNum;
224  MemoryRegion* region = pOutput.memArea()->request(
225                                     getELF64LastStartOffset(pOutput),
226                                     header_size);
227  Elf64_Shdr* shdr = (Elf64_Shdr*)region->start();
228
229  // Iterate the SectionTable in LDContext
230  unsigned int sectIdx = 0;
231  unsigned int shstridx = 0; // NULL section has empty name
232  for (; sectIdx < sectNum; ++sectIdx) {
233    const LDSection *ld_sect = pOutput.context()->getSection(sectIdx);
234    shdr[sectIdx].sh_name      = shstridx;
235    shdr[sectIdx].sh_type      = ld_sect->type();
236    shdr[sectIdx].sh_flags     = ld_sect->flag();
237    shdr[sectIdx].sh_addr      = ld_sect->addr();
238    shdr[sectIdx].sh_offset    = ld_sect->offset();
239    shdr[sectIdx].sh_size      = ld_sect->size();
240    shdr[sectIdx].sh_addralign = (ld_sect->hasSectionData())?
241                                   ld_sect->getSectionData()->getAlignment():
242                                   0x0;
243
244    shdr[sectIdx].sh_entsize   = getELF64SectEntrySize(*ld_sect);
245    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pOutput);
246    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect, pOutput);
247
248    // adjust strshidx
249    shstridx += ld_sect->name().size() + 1;
250  }
251}
252
253
254/// emitELF32ProgramHeader - emit Elf32_Phdr
255void ELFWriter::emitELF32ProgramHeader(Output& pOutput,
256                                       const GNULDBackend& pBackend) const
257{
258  assert(pOutput.hasMemArea());
259
260  uint64_t start_offset, phdr_size;
261
262  start_offset = sizeof(Elf32_Ehdr);
263  phdr_size = sizeof(Elf32_Phdr);
264  // Program header must start directly after ELF header
265  MemoryRegion *region = pOutput.memArea()->request(start_offset,
266                                          pBackend.numOfSegments() * phdr_size);
267
268  Elf32_Phdr* phdr = (Elf32_Phdr*)region->start();
269
270  // Iterate the elf segment table in GNULDBackend
271  size_t index = 0;
272  ELFSegmentFactory::const_iterator seg = pBackend.elfSegmentTable().begin(),
273                                 segEnd = pBackend.elfSegmentTable().end();
274  for (; seg != segEnd; ++seg, ++index) {
275    phdr[index].p_type   = (*seg).type();
276    phdr[index].p_flags  = (*seg).flag();
277    phdr[index].p_offset = (*seg).offset();
278    phdr[index].p_vaddr  = (*seg).vaddr();
279    phdr[index].p_paddr  = (*seg).paddr();
280    phdr[index].p_filesz = (*seg).filesz();
281    phdr[index].p_memsz  = (*seg).memsz();
282    phdr[index].p_align  = (*seg).align();
283  }
284}
285
286/// emitELF64ProgramHeader - emit ElfR64Phdr
287void ELFWriter::emitELF64ProgramHeader(Output& pOutput,
288                                       const GNULDBackend& pBackend) const
289{
290  assert(pOutput.hasMemArea());
291
292  uint64_t start_offset, phdr_size;
293
294  start_offset = sizeof(Elf64_Ehdr);
295  phdr_size = sizeof(Elf64_Phdr);
296  // Program header must start directly after ELF header
297  MemoryRegion *region = pOutput.memArea()->request(start_offset,
298                                          pBackend.numOfSegments() * phdr_size);
299  Elf64_Phdr* phdr = (Elf64_Phdr*)region->start();
300
301  // Iterate the elf segment table in GNULDBackend
302  size_t index = 0;
303  ELFSegmentFactory::const_iterator seg = pBackend.elfSegmentTable().begin(),
304                                 segEnd = pBackend.elfSegmentTable().end();
305  for (; seg != segEnd; ++seg, ++index) {
306    phdr[index].p_type   = (*seg).type();
307    phdr[index].p_flags  = (*seg).flag();
308    phdr[index].p_offset = (*seg).offset();
309    phdr[index].p_vaddr  = (*seg).vaddr();
310    phdr[index].p_paddr  = (*seg).paddr();
311    phdr[index].p_filesz = (*seg).filesz();
312    phdr[index].p_memsz  = (*seg).memsz();
313    phdr[index].p_align  = (*seg).align();
314  }
315}
316
317/// emitELF32ShStrTab - emit section string table
318void ELFWriter::emitELF32ShStrTab(Output& pOutput, MCLinker& pLinker) const
319{
320  uint64_t shstroffset = getELF32LastStartOffset(pOutput);
321
322  // get shstrtab
323  LDSection& shstrtab = pLinker.getOrCreateOutputSectHdr(".shstrtab",
324                                                         LDFileFormat::NamePool,
325                                                         SHT_STRTAB,
326                                                         0x0);
327  if (0 != shstrtab.size())
328    llvm::report_fatal_error(".shstrtab has been set.\n");
329
330  // compute size
331  unsigned int shstrsize = 0;
332  LDContext::const_sect_iterator section, sectEnd = pOutput.context()->sectEnd();
333  for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
334    shstrsize += (*section)->name().size() + 1;
335  }
336
337  shstrtab.setSize(shstrsize);
338  shstrtab.setOffset(shstroffset);
339
340  // write out data
341  MemoryRegion* region = pOutput.memArea()->request(shstrtab.offset(),
342                                                    shstrtab.size());
343  unsigned char* data = region->start();
344  shstrsize = 0;
345  for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
346    strcpy((char*)(data + shstrsize), (*section)->name().c_str());
347    shstrsize += (*section)->name().size() + 1;
348  }
349
350  shstrtab.setKind(LDFileFormat::NamePool);
351  shstrtab.setType(llvm::ELF::SHT_STRTAB);
352  shstrtab.setFlag(0x0);
353  shstrtab.setAddr(0x0);
354}
355
356
357/// emitELF64ShStrTab - emit section string table
358void ELFWriter::emitELF64ShStrTab(Output& pOutput, MCLinker& pLinker) const
359{
360  uint64_t shstroffset = getELF64LastStartOffset(pOutput);
361
362  // get shstrtab
363  LDSection& shstrtab = pLinker.getOrCreateOutputSectHdr(".shstrtab",
364                                                         LDFileFormat::NamePool,
365                                                         SHT_STRTAB,
366                                                         0x0);
367  if (0 != shstrtab.size())
368    llvm::report_fatal_error(".shstrtab has been set.\n");
369
370  // compute offset
371
372  // compute size
373  unsigned int shstrsize = 0;
374  LDContext::const_sect_iterator section, sectEnd = pOutput.context()->sectEnd();
375  for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
376    shstrsize += (*section)->name().size() + 1;
377  }
378
379  shstrtab.setSize(shstrsize);
380  shstrtab.setOffset(shstroffset);
381
382  // write out data
383  MemoryRegion* region = pOutput.memArea()->request(shstrtab.offset(),
384                                                    shstrtab.size());
385  unsigned char* data = region->start();
386  shstrsize = 0;
387  for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
388    strcpy((char*)(data + shstrsize), (*section)->name().c_str());
389    shstrsize += (*section)->name().size() + 1;
390  }
391
392  shstrtab.setKind(LDFileFormat::NamePool);
393  shstrtab.setType(llvm::ELF::SHT_STRTAB);
394  shstrtab.setFlag(0x0);
395  shstrtab.setAddr(0x0);
396}
397
398/// emitSectionData
399void
400ELFWriter::emitSectionData(const Layout& pLayout,
401                           const LDSection& pSection,
402                           MemoryRegion& pRegion) const
403{
404  const SectionData* data = pSection.getSectionData();
405  SectionData::const_iterator fragIter, fragEnd = data->end();
406  size_t cur_offset = 0;
407  for (fragIter = data->begin(); fragIter != fragEnd; ++fragIter) {
408    size_t size = computeFragmentSize(pLayout, *fragIter);
409    switch(fragIter->getKind()) {
410      case Fragment::Region: {
411        const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
412        const uint8_t* from = region_frag.getRegion().start();
413        memcpy(pRegion.getBuffer(cur_offset), from, size);
414        break;
415      }
416      case Fragment::Alignment: {
417        // TODO: emit values with different sizes (> 1 byte), and emit nops
418        AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
419        uint64_t count = size / align_frag.getValueSize();
420        switch (align_frag.getValueSize()) {
421          case 1u:
422            std::memset(pRegion.getBuffer(cur_offset),
423                        align_frag.getValue(),
424                        count);
425            break;
426          default:
427            llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
428            break;
429        }
430        break;
431      }
432      case Fragment::Fillment: {
433        FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
434        if (0 == size ||
435            0 == fill_frag.getValueSize() ||
436            0 == fill_frag.getSize()) {
437          // ignore virtual fillment
438          break;
439        }
440
441        uint64_t num_tiles = fill_frag.getSize() / fill_frag.getValueSize();
442        for (uint64_t i = 0; i != num_tiles; ++i) {
443          std::memset(pRegion.getBuffer(cur_offset),
444                      fill_frag.getValue(),
445                      fill_frag.getValueSize());
446        }
447        break;
448      }
449      case Fragment::Relocation:
450        llvm::report_fatal_error("relocation fragment should not be in a regular section.\n");
451        break;
452      case Fragment::Target:
453        llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
454        break;
455      default:
456        llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
457        break;
458    }
459    cur_offset += size;
460  }
461}
462
463/// emitRelocation
464void ELFWriter::emitRelocation(const Layout& pLayout,
465                               const Output& pOutput,
466                               const LDSection& pSection,
467                               MemoryRegion& pRegion) const
468{
469  const SectionData* sect_data = pSection.getSectionData();
470  assert(NULL != sect_data && "SectionData is NULL in emitRelocation!");
471
472  if (pSection.type() == SHT_REL)
473    emitRel(pLayout, pOutput, *sect_data, pRegion);
474  else if (pSection.type() == SHT_RELA)
475    emitRela(pLayout, pOutput, *sect_data, pRegion);
476  else
477    llvm::report_fatal_error("unsupported relocation section type!");
478}
479
480
481/// emitRel
482void ELFWriter::emitRel(const Layout& pLayout,
483                        const Output& pOutput,
484                        const SectionData& pSectionData,
485                        MemoryRegion& pRegion) const
486{
487  Elf32_Rel* rel = reinterpret_cast<Elf32_Rel*>(pRegion.start());
488
489  Relocation* relocation = 0;
490  FragmentRef* frag_ref = 0;
491
492  for (SectionData::const_iterator it = pSectionData.begin(),
493       ie = pSectionData.end(); it != ie; ++it, ++rel) {
494
495    relocation = &(llvm::cast<Relocation>(*it));
496    frag_ref = &(relocation->targetRef());
497
498    if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) {
499      rel->r_offset = static_cast<Elf32_Addr>(
500                      frag_ref->frag()->getParent()->getSection().addr() +
501                      pLayout.getOutputOffset(*frag_ref));
502    }
503    else {
504      rel->r_offset = static_cast<Elf32_Addr>(
505                      frag_ref->frag()->getParent()->getSection().offset() +
506                      pLayout.getOutputOffset(*frag_ref));
507    }
508
509    Elf32_Word Index;
510    if( relocation->symInfo() == NULL )
511      Index = 0;
512    else
513      Index = static_cast<Elf32_Word>(
514              f_Backend.getSymbolIdx(relocation->symInfo()->outSymbol()));
515
516    rel->setSymbolAndType(Index, relocation->type());
517  }
518}
519
520/// emitRela
521void ELFWriter::emitRela(const Layout& pLayout,
522                         const Output& pOutput,
523                         const SectionData& pSectionData,
524                         MemoryRegion& pRegion) const
525{
526  Elf32_Rela* rel = reinterpret_cast<Elf32_Rela*>(pRegion.start());
527
528  Relocation* relocation = 0;
529  FragmentRef* frag_ref = 0;
530
531  for (SectionData::const_iterator it = pSectionData.begin(),
532       ie = pSectionData.end(); it != ie; ++it, ++rel) {
533
534    relocation = &(llvm::cast<Relocation>(*it));
535    frag_ref = &(relocation->targetRef());
536
537    if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) {
538      rel->r_offset = static_cast<Elf32_Addr>(
539                      frag_ref->frag()->getParent()->getSection().addr() +
540                      pLayout.getOutputOffset(*frag_ref));
541    }
542    else {
543      rel->r_offset = static_cast<Elf32_Addr>(
544                      frag_ref->frag()->getParent()->getSection().offset() +
545                      pLayout.getOutputOffset(*frag_ref));
546    }
547
548    Elf32_Word Index;
549    if( relocation->symInfo() == NULL )
550      Index = 0;
551    else
552      Index = static_cast<Elf32_Word>(
553              f_Backend.getSymbolIdx(relocation->symInfo()->outSymbol()));
554
555    rel->setSymbolAndType(Index, relocation->type());
556    rel->r_addend = relocation->addend();
557  }
558}
559
560/// getELF32SectEntrySize - compute Elf32_Shdr::sh_entsize
561uint64_t ELFWriter::getELF32SectEntrySize(const LDSection& pSection) const
562{
563  if (llvm::ELF::SHT_DYNSYM == pSection.type() ||
564      llvm::ELF::SHT_SYMTAB == pSection.type())
565    return sizeof(llvm::ELF::Elf32_Sym);
566  if (llvm::ELF::SHT_REL == pSection.type())
567    return sizeof(llvm::ELF::Elf32_Rel);
568  if (llvm::ELF::SHT_RELA == pSection.type())
569    return sizeof(llvm::ELF::Elf32_Rela);
570  if (llvm::ELF::SHT_HASH == pSection.type())
571    return sizeof(llvm::ELF::Elf32_Word);
572  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
573    return sizeof(llvm::ELF::Elf32_Dyn);
574  return 0x0;
575}
576
577/// getELF64SectEntrySize - compute Elf64_Shdr::sh_entsize
578uint64_t ELFWriter::getELF64SectEntrySize(const LDSection& pSection) const
579{
580  if (llvm::ELF::SHT_DYNSYM == pSection.type() ||
581      llvm::ELF::SHT_SYMTAB == pSection.type())
582    return sizeof(llvm::ELF::Elf64_Sym);
583  if (llvm::ELF::SHT_REL == pSection.type())
584    return sizeof(llvm::ELF::Elf64_Rel);
585  if (llvm::ELF::SHT_RELA == pSection.type())
586    return sizeof(llvm::ELF::Elf64_Rela);
587  if (llvm::ELF::SHT_HASH == pSection.type())
588    return sizeof(llvm::ELF::Elf64_Word);
589  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
590    return sizeof(llvm::ELF::Elf64_Dyn);
591  return 0x0;
592}
593
594/// getSectLink - compute ElfXX_Shdr::sh_link
595uint64_t ELFWriter::getSectLink(const LDSection& pSection, const Output& pOutput) const
596{
597  const LDContext* context = pOutput.context();
598  if (llvm::ELF::SHT_SYMTAB == pSection.type())
599    return context->getSectionIdx(".strtab");
600  if (llvm::ELF::SHT_DYNSYM == pSection.type())
601    return context->getSectionIdx(".dynstr");
602  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
603    return context->getSectionIdx(".dynstr");
604  if (llvm::ELF::SHT_HASH == pSection.type())
605    return context->getSectionIdx(".dynsym");
606  if (llvm::ELF::SHT_REL == pSection.type() ||
607      llvm::ELF::SHT_RELA == pSection.type()) {
608    if (pOutput.type() == Output::Object)
609      return context->getSectionIdx(".symtab");
610    else
611      return context->getSectionIdx(".dynsym");
612  }
613  return llvm::ELF::SHN_UNDEF;
614}
615
616/// getSectInfo - compute ElfXX_Shdr::sh_info
617uint64_t ELFWriter::getSectInfo(const LDSection& pSection, const Output& pOutput) const
618{
619  const LDSection* info_link = pSection.getLink();
620  if (NULL == info_link)
621    return 0x0;
622  return info_link->index();
623}
624
625/// getELF32LastStartOffset
626uint64_t ELFWriter::getELF32LastStartOffset(const Output& pOutput) const
627{
628  LDSection* lastSect = pOutput.context()->getSectionTable().back();
629  assert(lastSect != NULL);
630  return Align<32>(lastSect->offset() + lastSect->size());
631}
632
633/// getELF64LastStartOffset
634uint64_t ELFWriter::getELF64LastStartOffset(const Output& pOutput) const
635{
636  LDSection* lastSect = pOutput.context()->getSectionTable().back();
637  assert(lastSect != NULL);
638  return Align<64>(lastSect->offset() + lastSect->size());
639}
640
641