1//===- LinkerConfig.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/Support/LinkerConfig.h"
11#include "alone/Support/Log.h"
12
13#include <llvm/Support/Signals.h>
14
15#include <mcld/MC/MCLDInfo.h>
16#include <mcld/MC/MCLDFile.h>
17#include <mcld/MC/MCLDDirectory.h>
18#include <mcld/LD/TextDiagnosticPrinter.h>
19#include <mcld/Support/Path.h>
20#include <mcld/Support/MsgHandling.h>
21#include <mcld/Support/raw_ostream.h>
22
23using namespace alone;
24
25LinkerConfig::LinkerConfig(const std::string &pTriple)
26  : mTriple(pTriple), mShared(false), mSOName(), mTarget(NULL), mLDInfo(NULL),
27    mDiagLineInfo(NULL), mDiagPrinter(NULL) {
28
29  initializeTarget();
30  initializeLDInfo();
31  initializeDiagnostic();
32}
33
34LinkerConfig::~LinkerConfig() {
35  delete mLDInfo;
36
37  if (mDiagPrinter->getNumErrors() != 0) {
38    // If here, the program failed ungracefully. Run the interrupt handlers to
39    // ensure any other cleanups (e.g., files that registered by
40    // RemoveFileOnSignal(...)) getting done before exit.
41    llvm::sys::RunInterruptHandlers();
42  }
43  mDiagPrinter->finish();
44
45  delete mDiagLineInfo;
46  delete mDiagPrinter;
47}
48
49bool LinkerConfig::initializeTarget() {
50  std::string error;
51  mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error);
52  if (NULL != mTarget) {
53    return true;
54  } else {
55    ALOGE("Cannot initialize mcld::Target for given triple '%s'! (%s)\n",
56          mTriple.c_str(), error.c_str());
57    return false;
58  }
59}
60
61bool LinkerConfig::initializeLDInfo() {
62  if (NULL != mLDInfo) {
63    ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
64          mTriple.c_str());
65    return false;
66  }
67
68  mLDInfo = new mcld::MCLDInfo(getTriple(), 1, 32);
69  return true;
70}
71
72bool LinkerConfig::initializeDiagnostic() {
73  // Set up MsgHandler.
74  mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
75
76  mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDInfo);
77
78  mcld::InitializeDiagnosticEngine(*mLDInfo, mDiagLineInfo, mDiagPrinter);
79
80  return true;
81}
82
83void LinkerConfig::setShared(bool pEnable) {
84  mShared = pEnable;
85  return;
86}
87
88void LinkerConfig::setBsymbolic(bool pEnable) {
89  mLDInfo->options().setBsymbolic(pEnable);
90  return;
91}
92
93void LinkerConfig::setSOName(const std::string &pSOName) {
94  mSOName = pSOName;
95  return;
96}
97
98void LinkerConfig::setDyld(const std::string &pDyld) {
99  mLDInfo->options().setDyld(pDyld);
100  return;
101}
102
103void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
104  mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
105  return;
106}
107
108void LinkerConfig::addWrap(const std::string &pWrapSymbol) {
109  bool exist = false;
110
111  // Add wname -> __wrap_wname.
112  mcld::StringEntry<llvm::StringRef>* to_wrap =
113               mLDInfo->scripts().renameMap().insert(pWrapSymbol, exist);
114
115  std::string to_wrap_str = "__wrap_" + pWrapSymbol;
116  to_wrap->setValue(to_wrap_str);
117
118  if (exist) {
119    mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str;
120  }
121
122  // Add __real_wname -> wname.
123  std::string from_real_str = "__real_" + pWrapSymbol;
124  mcld::StringEntry<llvm::StringRef>* from_real =
125             mLDInfo->scripts().renameMap().insert(from_real_str, exist);
126  from_real->setValue(pWrapSymbol);
127
128  if (exist) {
129    mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str;
130  }
131
132  return;
133}
134
135void LinkerConfig::addPortable(const std::string &pPortableSymbol) {
136  bool exist = false;
137
138  // Add pname -> pname_portable.
139  mcld::StringEntry<llvm::StringRef>* to_port =
140                mLDInfo->scripts().renameMap().insert(pPortableSymbol, exist);
141
142  std::string to_port_str = pPortableSymbol + "_portable";
143  to_port->setValue(to_port_str);
144
145  if (exist) {
146    mcld::warning(mcld::diag::rewrap) << pPortableSymbol << to_port_str;
147}
148
149  // Add __real_pname -> pname.
150  std::string from_real_str = "__real_" + pPortableSymbol;
151  mcld::StringEntry<llvm::StringRef>* from_real =
152           mLDInfo->scripts().renameMap().insert(from_real_str, exist);
153
154  from_real->setValue(pPortableSymbol);
155
156  if (exist) {
157    mcld::warning(mcld::diag::rewrap) << pPortableSymbol << from_real_str;
158  }
159
160  return;
161}
162
163void LinkerConfig::addSearchDir(const std::string &pDirPath) {
164  // SearchDirs will remove the created MCLDDirectory.
165  mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
166
167  if (sd->isInSysroot()) {
168    sd->setSysroot(mLDInfo->options().sysroot());
169  }
170
171  if (exists(sd->path()) && is_directory(sd->path())) {
172    mLDInfo->options().directories().add(*sd);
173  } else {
174    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
175  }
176
177  return;
178}
179