1//===- ELFExecWriter.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/ELFExecWriter.h>
10#include <mcld/LD/LDSymbol.h>
11#include <mcld/Target/GNULDBackend.h>
12#include <mcld/MC/MCLDInput.h>
13#include <mcld/MC/MCLDOutput.h>
14#include <mcld/MC/MCLDInfo.h>
15#include <mcld/MC/MCLinker.h>
16#include <llvm/Support/ELF.h>
17#include <vector>
18
19using namespace llvm;
20using namespace mcld;
21
22
23//==========================
24// ELFExecWriter
25ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker)
26  : ExecWriter(pBackend),
27    ELFWriter(pBackend),
28    m_Backend(pBackend),
29    m_Linker(pLinker) {
30
31}
32
33ELFExecWriter::~ELFExecWriter()
34{
35}
36
37llvm::error_code ELFExecWriter::writeExecutable(Output& pOutput)
38{
39  // write out the interpreter section: .interp
40  target().emitInterp(pOutput, m_Linker.getLDInfo());
41
42  // Write out name pool sections: .dynsym, .dynstr, .hash
43  target().emitDynNamePools(pOutput,
44                            m_Linker.getOutputSymbols(),
45                            m_Linker.getLayout(),
46                            m_Linker.getLDInfo());
47
48  // Write out name pool sections: .symtab, .strtab
49  target().emitRegNamePools(pOutput,
50                            m_Linker.getOutputSymbols(),
51                            m_Linker.getLayout(),
52                            m_Linker.getLDInfo());
53
54  // Write out regular ELF sections
55  unsigned int secIdx = 0;
56  unsigned int secEnd = pOutput.context()->numOfSections();
57  for (secIdx = 0; secIdx < secEnd; ++secIdx) {
58    LDSection* sect = pOutput.context()->getSection(secIdx);
59    MemoryRegion* region = NULL;
60    // request output region
61    switch(sect->kind()) {
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.memArea()->request(sect->offset(), sect->size());
69        if (NULL == region) {
70          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") +
71                                   llvm::Twine(secIdx) +
72                                   llvm::Twine("] - `") +
73                                   sect->name() +
74                                   llvm::Twine("'.\n"));
75        }
76        break;
77      }
78      case LDFileFormat::Null:
79      case LDFileFormat::NamePool:
80      case LDFileFormat::BSS:
81      case LDFileFormat::Note:
82      case LDFileFormat::MetaData:
83      case LDFileFormat::Version:
84      case LDFileFormat::EhFrameHdr:
85        // ignore these sections
86        continue;
87      default: {
88        llvm::errs() << "WARNING: unsupported section kind: "
89                     << sect->kind()
90                     << " of section "
91                     << sect->name()
92                     << ".\n";
93        continue;
94      }
95    }
96
97    // write out sections with data
98    switch(sect->kind()) {
99      case LDFileFormat::Regular:
100      case LDFileFormat::Debug:
101      case LDFileFormat::GCCExceptTable:
102      case LDFileFormat::EhFrame: {
103        // FIXME: if optimization of exception handling sections is enabled,
104        // then we should emit these sections by the other way.
105        emitSectionData(m_Linker.getLayout(), *sect, *region);
106        break;
107      }
108      case LDFileFormat::Relocation:
109        emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
110        break;
111      case LDFileFormat::Target:
112        target().emitSectionData(pOutput,
113                                 *sect,
114                                 m_Linker.getLDInfo(),
115                                 m_Linker.getLayout(),
116                                 *region);
117        break;
118      default:
119        continue;
120    }
121  } // end of for loop
122
123  if (32 == target().bitclass()) {
124    // Write out ELF header
125    // Write out section header table
126    emitELF32ShStrTab(pOutput, m_Linker);
127
128    writeELF32Header(m_Linker.getLDInfo(),
129                     m_Linker.getLayout(),
130                     target(),
131                     pOutput);
132
133    emitELF32ProgramHeader(pOutput, target());
134
135    emitELF32SectionHeader(pOutput, m_Linker);
136  }
137  else if (64 == target().bitclass()) {
138    // Write out ELF header
139    // Write out section header table
140    emitELF64ShStrTab(pOutput, m_Linker);
141
142    writeELF64Header(m_Linker.getLDInfo(),
143                     m_Linker.getLayout(),
144                     target(),
145                     pOutput);
146
147    emitELF64ProgramHeader(pOutput, target());
148
149    emitELF64SectionHeader(pOutput, m_Linker);
150  }
151  else
152    return make_error_code(errc::not_supported);
153
154  pOutput.memArea()->clear();
155  return llvm::make_error_code(llvm::errc::success);
156}
157
158