Linker.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
1//===- Linker.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/Linker.h>
10#include <mcld/LinkerConfig.h>
11#include <mcld/Module.h>
12#include <mcld/IRBuilder.h>
13
14#include <mcld/Support/MsgHandling.h>
15#include <mcld/Support/TargetRegistry.h>
16#include <mcld/Support/FileHandle.h>
17#include <mcld/Support/MemoryArea.h>
18#include <mcld/Support/raw_ostream.h>
19
20#include <mcld/Object/ObjectLinker.h>
21#include <mcld/MC/InputBuilder.h>
22#include <mcld/Target/TargetLDBackend.h>
23#include <mcld/LD/LDSection.h>
24#include <mcld/LD/LDSymbol.h>
25#include <mcld/Fragment/FragmentRef.h>
26
27#include <cassert>
28
29using namespace mcld;
30
31Linker::Linker()
32  : m_pConfig(NULL), m_pModule(NULL), m_pIRBuilder(NULL),
33    m_pTarget(NULL), m_pBackend(NULL), m_pObjLinker(NULL) {
34}
35
36Linker::~Linker()
37{
38  reset();
39}
40
41bool Linker::config(LinkerConfig& pConfig)
42{
43  m_pConfig = &pConfig;
44
45  if (!initTarget())
46    return false;
47
48  if (!initBackend())
49    return false;
50
51  if (!initEmulator())
52    return false;
53
54  if (!initOStream())
55    return false;
56
57  return true;
58}
59
60bool Linker::link(Module& pModule, IRBuilder& pBuilder)
61{
62  assert(NULL != m_pConfig);
63
64  m_pIRBuilder = &pBuilder;
65  m_pObjLinker = new ObjectLinker(*m_pConfig,
66                                  pModule,
67                                  m_pIRBuilder->getInputBuilder(),
68                                  *m_pBackend);
69
70  // 2. - initialize FragmentLinker
71  if (!m_pObjLinker->initFragmentLinker())
72    return false;
73
74  // 3. - initialize output's standard sections
75  if (!m_pObjLinker->initStdSections())
76    return false;
77
78  // 4. - normalize the input tree
79  m_pObjLinker->normalize();
80
81  if (m_pConfig->options().trace()) {
82    static int counter = 0;
83    mcld::outs() << "** name\ttype\tpath\tsize (" << pModule.getInputTree().size() << ")\n";
84    InputTree::const_dfs_iterator input, inEnd = pModule.getInputTree().dfs_end();
85    for (input=pModule.getInputTree().dfs_begin(); input!=inEnd; ++input) {
86      mcld::outs() << counter++ << " *  " << (*input)->name();
87      switch((*input)->type()) {
88      case Input::Archive:
89        mcld::outs() << "\tarchive\t(";
90        break;
91      case Input::Object:
92        mcld::outs() << "\tobject\t(";
93        break;
94      case Input::DynObj:
95        mcld::outs() << "\tshared\t(";
96        break;
97      case Input::Script:
98        mcld::outs() << "\tscript\t(";
99        break;
100      case Input::External:
101        mcld::outs() << "\textern\t(";
102        break;
103      default:
104        unreachable(diag::err_cannot_trace_file) << (*input)->type()
105                                                 << (*input)->name()
106                                                 << (*input)->path();
107      }
108      mcld::outs() << (*input)->path() << ")\n";
109    }
110  }
111
112  // 5. - check if we can do static linking and if we use split-stack.
113  if (!m_pObjLinker->linkable())
114    return Diagnose();
115
116  // 6. - read all relocation entries from input files
117  m_pObjLinker->readRelocations();
118
119  // 7. - merge all sections
120  if (!m_pObjLinker->mergeSections())
121    return false;
122
123  // 8. - add standard symbols and target-dependent symbols
124  // m_pObjLinker->addUndefSymbols();
125  if (!m_pObjLinker->addStandardSymbols() ||
126      !m_pObjLinker->addTargetSymbols())
127    return false;
128
129  // 9. - scan all relocation entries by output symbols.
130  m_pObjLinker->scanRelocations();
131
132  // 10.a - pre-layout
133  m_pObjLinker->prelayout();
134
135  // 10.b - linear layout
136  m_pObjLinker->layout();
137
138  // 10.c - post-layout (create segment, instruction relaxing)
139  m_pObjLinker->postlayout();
140
141  // 11. - finalize symbol value
142  m_pObjLinker->finalizeSymbolValue();
143
144  // 12. - apply relocations
145  m_pObjLinker->relocation();
146
147  if (!Diagnose())
148    return false;
149  return true;
150}
151
152bool Linker::emit(MemoryArea& pOutput)
153{
154  // 13. - write out output
155  m_pObjLinker->emitOutput(pOutput);
156
157  // 14. - post processing
158  m_pObjLinker->postProcessing(pOutput);
159
160  if (!Diagnose())
161    return false;
162
163  return true;
164}
165
166bool Linker::emit(const std::string& pPath)
167{
168  FileHandle file;
169  FileHandle::Permission perm = 0755;
170  if (!file.open(pPath,
171            FileHandle::ReadWrite | FileHandle::Truncate | FileHandle::Create,
172            perm)) {
173    error(diag::err_cannot_open_output_file) << "Linker::emit()" << pPath;
174    return false;
175  }
176
177  MemoryArea* output = new MemoryArea(file);
178
179  bool result = emit(*output);
180
181  delete output;
182  file.close();
183  return result;
184}
185
186bool Linker::emit(int pFileDescriptor)
187{
188  FileHandle file;
189  file.delegate(pFileDescriptor);
190  MemoryArea* output = new MemoryArea(file);
191
192  bool result = emit(*output);
193
194  delete output;
195  file.close();
196  return result;
197}
198
199bool Linker::reset()
200{
201  m_pConfig = NULL;
202  m_pModule = NULL;
203  m_pIRBuilder = NULL;
204  m_pTarget = NULL;
205
206  delete m_pBackend;
207  m_pBackend = NULL;
208
209  delete m_pObjLinker;
210  m_pObjLinker = NULL;
211
212  LDSection::Clear();
213  LDSymbol::Clear();
214  FragmentRef::Clear();
215  return true;
216}
217
218bool Linker::initTarget()
219{
220  assert(NULL != m_pConfig);
221
222  std::string error;
223  m_pTarget = TargetRegistry::lookupTarget(m_pConfig->triple().str(), error);
224  if (NULL == m_pTarget) {
225    fatal(diag::fatal_cannot_init_target) << m_pConfig->triple().str() << error;
226    return false;
227  }
228  return true;
229}
230
231bool Linker::initBackend()
232{
233  assert(NULL != m_pTarget);
234  m_pBackend = m_pTarget->createLDBackend(*m_pConfig);
235  if (NULL == m_pBackend) {
236    fatal(diag::fatal_cannot_init_backend) << m_pConfig->triple().str();
237    return false;
238  }
239  return true;
240}
241
242bool Linker::initEmulator()
243{
244  assert(NULL != m_pTarget && NULL != m_pConfig);
245  return m_pTarget->emulate(m_pConfig->triple().str(), *m_pConfig);
246}
247
248bool Linker::initOStream()
249{
250  assert(NULL != m_pConfig);
251
252  mcld::outs().setColor(m_pConfig->options().color());
253  mcld::errs().setColor(m_pConfig->options().color());
254
255  return true;
256}
257
258