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
10#include "alone/Linker.h"
11#include "alone/Support/LinkerConfig.h"
12#include "alone/Support/MemoryFactory.h"
13#include "alone/Support/Log.h"
14
15#include <llvm/Support/ELF.h>
16
17#include <mcld/MC/MCLDDriver.h>
18#include <mcld/MC/InputTree.h>
19#include <mcld/MC/MCLinker.h>
20#include <mcld/MC/InputTree.h>
21#include <mcld/LD/LDSection.h>
22#include <mcld/LD/LDContext.h>
23#include <mcld/Target/TargetLDBackend.h>
24#include <mcld/Support/Path.h>
25#include <mcld/Support/MemoryArea.h>
26#include <mcld/Support/FileHandle.h>
27#include <mcld/Support/MemoryAreaFactory.h>
28#include <mcld/Support/TargetRegistry.h>
29
30using namespace alone;
31
32const char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode) {
33  static const char* ErrorString[] = {
34    /* kSuccess */
35    "Successfully compiled.",
36    /* kDoubleConfig */
37    "Configure Linker twice.",
38    /* kCreateBackend */
39    "Cannot create backend.",
40    /* kDelegateLDInfo */
41    "Cannot get linker information",
42    /* kFindNameSpec */
43    "Cannot find -lnamespec",
44    /* kOpenNameSpec */
45    "Cannot open -lnamespec",
46    /* kOpenObjectFile */
47    "Cannot open object file",
48    /* kNotConfig */
49    "Linker::config() is not called",
50    /* kNotSetUpOutput */
51    "Linker::setOutput() is not called before add input files",
52    /* kOpenOutput */
53    "Cannot open output file",
54    /* kReadSections */
55    "Cannot read sections",
56    /* kReadSymbols */
57    "Cannot read symbols",
58    /* kAddAdditionalSymbols */
59    "Cannot add standard and target symbols",
60    /* kMaxErrorCode */
61    "(Unknown error code)"
62  };
63
64  if (pErrCode > kMaxErrorCode) {
65    pErrCode = kMaxErrorCode;
66  }
67
68  return ErrorString[ static_cast<size_t>(pErrCode) ];
69}
70
71//===----------------------------------------------------------------------===//
72// Linker
73//===----------------------------------------------------------------------===//
74Linker::Linker()
75  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
76    mRoot(NULL), mShared(false) {
77}
78
79Linker::Linker(const LinkerConfig& pConfig)
80  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
81    mRoot(NULL), mShared(false) {
82
83  const std::string &triple = pConfig.getTriple();
84
85  enum ErrorCode err = config(pConfig);
86  if (kSuccess != err) {
87    ALOGE("%s (%s)", GetErrorString(err), triple.c_str());
88    return;
89  }
90
91  return;
92}
93
94Linker::~Linker() {
95  delete mDriver;
96  delete mBackend;
97  delete mMemAreaFactory;
98  delete mRoot;
99}
100
101enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
102  mLDInfo = const_cast<mcld::MCLDInfo*>(pConfig.getLDInfo());
103  if (mLDInfo == NULL) {
104    return kDelegateLDInfo;
105  }
106
107  mRoot = new mcld::InputTree::iterator(mLDInfo->inputs().root());
108  mShared = pConfig.isShared();
109  mSOName = pConfig.getSOName();
110
111  return kSuccess;
112}
113
114enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
115  if (mLDInfo != NULL) {
116    return kDoubleConfig;
117  }
118
119  extractFiles(pConfig);
120
121  mBackend = pConfig.getTarget()->createLDBackend(pConfig.getTriple());
122  if (mBackend == NULL) {
123    return kCreateBackend;
124  }
125
126  mMemAreaFactory = new MemoryFactory();
127
128  mDriver = new mcld::MCLDDriver(*mLDInfo, *mBackend, *mMemAreaFactory);
129
130  mDriver->initMCLinker();
131
132  return kSuccess;
133}
134
135void Linker::advanceRoot() {
136  if (mRoot->isRoot()) {
137    mRoot->move<mcld::TreeIteratorBase::Leftward>();
138  } else {
139    mRoot->move<mcld::TreeIteratorBase::Rightward>();
140  }
141  return;
142}
143
144enum Linker::ErrorCode Linker::openFile(const mcld::sys::fs::Path& pPath,
145                                        enum Linker::ErrorCode pCode,
146                                        mcld::Input& pInput) {
147  mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pPath,
148                                                    mcld::FileHandle::ReadOnly);
149
150  if (input_memory->handler()->isGood()) {
151    pInput.setMemArea(input_memory);
152  } else {
153    return pCode;
154  }
155
156  mcld::LDContext *input_context = mLDInfo->contextFactory().produce(pPath);
157  pInput.setContext(input_context);
158  return kSuccess;
159}
160
161enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
162  mcld::sys::fs::Path* path = NULL;
163  // find out the real path of the namespec.
164  if (mLDInfo->attrFactory().constraint().isSharedSystem()) {
165    // In the system with shared object support, we can find both archive
166    // and shared object.
167
168    if (mLDInfo->attrFactory().last().isStatic()) {
169      // with --static, we must search an archive.
170      path = mLDInfo->options().directories().find(pNameSpec,
171                                                   mcld::Input::Archive);
172    }
173    else {
174      // otherwise, with --Bdynamic, we can find either an archive or a
175      // shared object.
176      path = mLDInfo->options().directories().find(pNameSpec,
177                                                   mcld::Input::DynObj);
178    }
179  }
180  else {
181    // In the system without shared object support, we only look for an
182    // archive.
183    path = mLDInfo->options().directories().find(pNameSpec,
184                                                 mcld::Input::Archive);
185  }
186
187  if (NULL == path)
188    return kFindNameSpec;
189
190  mcld::Input* input = mLDInfo->inputFactory().produce(pNameSpec, *path,
191                                                       mcld::Input::Unknown);
192  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
193
194  advanceRoot();
195
196  return openFile(*path, kOpenNameSpec, *input);
197}
198
199/// addObject - Add a object file by the filename.
200enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
201  mcld::Input* input = mLDInfo->inputFactory().produce(pObjectPath,
202                                                       pObjectPath,
203                                                       mcld::Input::Unknown);
204
205  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
206
207  advanceRoot();
208
209  return openFile(pObjectPath, kOpenObjectFile, *input);
210}
211
212/// addObject - Add a piece of memory. The memory is of ELF format.
213enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
214
215  mcld::Input* input = mLDInfo->inputFactory().produce("memory object",
216                                                       "NAN",
217                                                       mcld::Input::Unknown);
218
219  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
220
221  advanceRoot();
222
223  mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
224  input->setMemArea(input_memory);
225
226  mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
227  input->setContext(input_context);
228
229  return kSuccess;
230}
231
232enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
233  mcld::Input* input = mLDInfo->inputFactory().produce("code object",
234                                                       "NAN",
235                                                       mcld::Input::External);
236
237  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
238
239  advanceRoot();
240
241  mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
242  input->setMemArea(input_memory);
243
244  mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
245  input->setContext(input_context);
246
247  // FIXME: So far, MCLinker must set up output before add input files.
248  // set up LDContext
249  if (mDriver->hasInitLinker()) {
250    return kNotConfig;
251  }
252
253  if (!mLDInfo->output().hasContext()) {
254    return kNotSetUpOutput;
255  }
256
257  // create NULL section
258  mcld::LDSection& null =
259      mDriver->getLinker()->createSectHdr("",
260                                          mcld::LDFileFormat::Null,
261                                          llvm::ELF::SHT_NULL,
262                                          0);
263
264  null.setSize(0);
265  null.setOffset(0);
266  null.setIndex(0);
267  null.setInfo(0);
268  null.setAlign(0);
269
270  input_context->getSectionTable().push_back(&null);
271
272  // create .text section
273  mcld::LDSection& text = mDriver->getLinker()->createSectHdr(".text",
274                              mcld::LDFileFormat::Regular,
275                              llvm::ELF::SHT_PROGBITS,
276                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR);
277
278  text.setSize(pSize);
279  text.setOffset(0x0);
280  text.setIndex(1);
281  text.setInfo(0);
282  text.setAlign(1);
283
284  input_context->getSectionTable().push_back(&text);
285
286  return kSuccess;
287}
288
289enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
290  if (mLDInfo->output().hasContext()) {
291    return kDoubleConfig;
292  }
293
294  // -----  initialize output file  ----- //
295
296  mcld::FileHandle::Permission perm = 0755;
297
298  mcld::MemoryArea* out_area = mMemAreaFactory->produce(
299                      pPath,
300                      mcld::FileHandle::ReadWrite |
301                        mcld::FileHandle::Truncate |
302                        mcld::FileHandle::Create,
303                      perm);
304
305  if (!out_area->handler()->isGood()) {
306    return kOpenOutput;
307  }
308
309  if (mShared) {
310    mLDInfo->output().setType(mcld::Output::DynObj);
311  } else {
312    mLDInfo->output().setType(mcld::Output::Exec);
313  }
314
315  mLDInfo->output().setSOName(mSOName);
316  mLDInfo->output().setMemArea(out_area);
317  mLDInfo->output().setContext(mLDInfo->contextFactory().produce(pPath));
318
319  // FIXME: We must initialize MCLinker before setOutput, and initialize
320  // standard sections here. This is because we have to build the section
321  // map before input files using it.
322  if (!mDriver->hasInitLinker()) {
323    return kNotConfig;
324  }
325
326  mDriver->initStdSections();
327
328  return kSuccess;
329}
330
331enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
332  if (mLDInfo->output().hasContext()) {
333    return kDoubleConfig;
334  }
335
336  // -----  initialize output file  ----- //
337  mcld::MemoryArea* out_area = mMemAreaFactory->produce(pFileHandler);
338
339  mLDInfo->output().setType(mcld::Output::DynObj);
340  mLDInfo->output().setMemArea(out_area);
341  mLDInfo->output().setContext(mLDInfo->contextFactory().produce());
342
343  // FIXME: We must initialize MCLinker before setOutput, and initialize
344  // standard sections here. This is because we have to build the section
345  // map before input files using it.
346  if (!mDriver->hasInitLinker()) {
347    return kNotConfig;
348  }
349
350  mDriver->initStdSections();
351
352  return kSuccess;
353}
354
355enum Linker::ErrorCode Linker::link() {
356  mDriver->normalize();
357
358  if (!mDriver->mergeSections()) {
359    return kReadSections;
360  }
361
362  if (!mDriver->addStandardSymbols() || !mDriver->addTargetSymbols()) {
363    return kAddAdditionalSymbols;
364  }
365
366  mDriver->readRelocations();
367  mDriver->prelayout();
368  mDriver->layout();
369  mDriver->postlayout();
370  mDriver->finalizeSymbolValue();
371  mDriver->relocation();
372  mDriver->emitOutput();
373  mDriver->postProcessing();
374
375  return kSuccess;
376}
377
378