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