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