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