• Home
  • 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