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/MCLDDirectory.h>
16 #include <mcld/MC/ZOption.h>
17 #include <mcld/LD/TextDiagnosticPrinter.h>
18 #include <mcld/Support/Path.h>
19 #include <mcld/Support/MsgHandling.h>
20 #include <mcld/Support/raw_ostream.h>
21
22 using namespace alone;
23
LinkerConfig(const std::string & pTriple)24 LinkerConfig::LinkerConfig(const std::string &pTriple)
25 : mTriple(pTriple), mSOName(), mTarget(NULL), mLDConfig(NULL),
26 mLDScript(NULL), mDiagLineInfo(NULL), mDiagPrinter(NULL) {
27
28 initializeTarget();
29 initializeLDScript();
30 initializeLDInfo();
31 initializeDiagnostic();
32 }
33
~LinkerConfig()34 LinkerConfig::~LinkerConfig() {
35 delete mLDConfig;
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 mLDScript;
46 delete mDiagLineInfo;
47 delete mDiagPrinter;
48 }
49
initializeTarget()50 bool LinkerConfig::initializeTarget() {
51 std::string error;
52 mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error);
53 if (NULL != mTarget) {
54 return true;
55 } else {
56 ALOGE("Cannot initialize mcld::Target for given triple '%s'! (%s)\n",
57 mTriple.c_str(), error.c_str());
58 return false;
59 }
60 }
61
initializeLDInfo()62 bool LinkerConfig::initializeLDInfo() {
63 if (NULL != mLDConfig) {
64 ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
65 mTriple.c_str());
66 return false;
67 }
68
69 mLDConfig = new mcld::LinkerConfig(getTriple());
70 mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
71
72 struct NameMap {
73 const char* from;
74 const char* to;
75 };
76
77 static const NameMap map[] =
78 {
79 {".text", ".text"},
80 {".rodata", ".rodata"},
81 {".data.rel.ro.local", ".data.rel.ro.local"},
82 {".data.rel.ro", ".data.rel.ro"},
83 {".data", ".data"},
84 {".bss", ".bss"},
85 {".tdata", ".tdata"},
86 {".tbss", ".tbss"},
87 {".init_array", ".init_array"},
88 {".fini_array", ".fini_array"},
89 // TODO: Support DT_INIT_ARRAY for all constructors?
90 {".ctors", ".ctors"},
91 {".dtors", ".dtors"},
92 // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
93 // sections would be handled differently.
94 {".sdata2", ".sdata"},
95 {".sbss2", ".sbss"},
96 {".sdata", ".sdata"},
97 {".sbss", ".sbss"},
98 {".lrodata", ".lrodata"},
99 {".ldata", ".ldata"},
100 {".lbss", ".lbss"},
101 {".gcc_except_table", ".gcc_except_table"},
102 {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
103 {".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
104 {".gnu.linkonce.r", ".rodata"},
105 {".gnu.linkonce.d", ".data"},
106 {".gnu.linkonce.b", ".bss"},
107 {".gnu.linkonce.sb2", ".sbss"},
108 {".gnu.linkonce.sb", ".sbss"},
109 {".gnu.linkonce.s2", ".sdata"},
110 {".gnu.linkonce.s", ".sdata"},
111 {".gnu.linkonce.wi", ".debug_info"},
112 {".gnu.linkonce.td", ".tdata"},
113 {".gnu.linkonce.tb", ".tbss"},
114 {".gnu.linkonce.t", ".text"},
115 {".gnu.linkonce.lr", ".lrodata"},
116 {".gnu.linkonce.lb", ".lbss"},
117 {".gnu.linkonce.l", ".ldata"},
118 };
119
120 if (mLDConfig->codeGenType() != mcld::LinkerConfig::Object) {
121 const unsigned int map_size = (sizeof(map) / sizeof(map[0]) );
122 for (unsigned int i = 0; i < map_size; ++i) {
123 bool exist = false;
124 mLDScript->sectionMap().append(map[i].from,
125 map[i].to,
126 exist);
127 }
128 }
129 return true;
130 }
131
initializeLDScript()132 bool LinkerConfig::initializeLDScript() {
133 mLDScript = new mcld::LinkerScript();
134 return true;
135 }
136
initializeDiagnostic()137 bool LinkerConfig::initializeDiagnostic() {
138 // Set up MsgHandler.
139 mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDConfig);
140
141 mcld::InitializeDiagnosticEngine(*mLDConfig, mDiagPrinter);
142
143 mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
144
145 mcld::getDiagnosticEngine().setLineInfo(*mDiagLineInfo);
146 return true;
147 }
148
isShared() const149 bool LinkerConfig::isShared() const {
150 return (mcld::LinkerConfig::DynObj == mLDConfig->codeGenType());
151 }
152
setShared(bool pEnable)153 void LinkerConfig::setShared(bool pEnable) {
154 if (pEnable)
155 mLDConfig->setCodeGenType(mcld::LinkerConfig::DynObj);
156 else
157 mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
158 return;
159 }
160
setBsymbolic(bool pEnable)161 void LinkerConfig::setBsymbolic(bool pEnable) {
162 mLDConfig->options().setBsymbolic(pEnable);
163 return;
164 }
165
setDefineCommon(bool pEnable)166 void LinkerConfig::setDefineCommon(bool pEnable) {
167 mLDConfig->options().setDefineCommon(pEnable);
168 return;
169 }
170
setSOName(const std::string & pSOName)171 void LinkerConfig::setSOName(const std::string &pSOName) {
172 mLDConfig->options().setSOName(pSOName);
173 return;
174 }
175
setDyld(const std::string & pDyld)176 void LinkerConfig::setDyld(const std::string &pDyld) {
177 mLDConfig->options().setDyld(pDyld);
178 return;
179 }
180
setSysRoot(const std::string & pSysRoot)181 void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
182 mLDScript->setSysroot(mcld::sys::fs::Path(pSysRoot));
183 return;
184 }
185
setZOption(unsigned int pOptions)186 void LinkerConfig::setZOption(unsigned int pOptions) {
187 mcld::ZOption option;
188 if (pOptions & kCombReloc) {
189 option.setKind(mcld::ZOption::CombReloc);
190 mLDConfig->options().addZOption(option);
191 }
192 else {
193 option.setKind(mcld::ZOption::NoCombReloc);
194 mLDConfig->options().addZOption(option);
195 }
196
197 if (pOptions & kDefs) {
198 option.setKind(mcld::ZOption::Defs);
199 mLDConfig->options().addZOption(option);
200 }
201
202 if (pOptions & kExecStack) {
203 option.setKind(mcld::ZOption::ExecStack);
204 mLDConfig->options().addZOption(option);
205 }
206 else {
207 option.setKind(mcld::ZOption::NoExecStack);
208 mLDConfig->options().addZOption(option);
209 }
210
211 if (pOptions & kInitFirst) {
212 option.setKind(mcld::ZOption::InitFirst);
213 mLDConfig->options().addZOption(option);
214 }
215
216 if (pOptions & kInterPose) {
217 option.setKind(mcld::ZOption::InterPose);
218 mLDConfig->options().addZOption(option);
219 }
220
221 if (pOptions & kLoadFltr) {
222 option.setKind(mcld::ZOption::LoadFltr);
223 mLDConfig->options().addZOption(option);
224 }
225
226 if (pOptions & kMulDefs) {
227 option.setKind(mcld::ZOption::MulDefs);
228 mLDConfig->options().addZOption(option);
229 }
230
231 if (pOptions & kNoCopyReloc) {
232 option.setKind(mcld::ZOption::NoCopyReloc);
233 mLDConfig->options().addZOption(option);
234 }
235
236 if (pOptions & kNoDefaultLib) {
237 option.setKind(mcld::ZOption::NoDefaultLib);
238 mLDConfig->options().addZOption(option);
239 }
240
241 if (pOptions & kNoDelete) {
242 option.setKind(mcld::ZOption::NoDelete);
243 mLDConfig->options().addZOption(option);
244 }
245
246 if (pOptions & kNoDLOpen) {
247 option.setKind(mcld::ZOption::NoDLOpen);
248 mLDConfig->options().addZOption(option);
249 }
250
251 if (pOptions & kNoDump) {
252 option.setKind(mcld::ZOption::NoDump);
253 mLDConfig->options().addZOption(option);
254 }
255
256 if (pOptions & kRelro) {
257 option.setKind(mcld::ZOption::Relro);
258 mLDConfig->options().addZOption(option);
259 }
260 else {
261 option.setKind(mcld::ZOption::NoRelro);
262 mLDConfig->options().addZOption(option);
263 }
264
265 if (pOptions & kLazy) {
266 option.setKind(mcld::ZOption::Lazy);
267 mLDConfig->options().addZOption(option);
268 }
269 else {
270 option.setKind(mcld::ZOption::Now);
271 mLDConfig->options().addZOption(option);
272 }
273
274 if (pOptions & kOrigin) {
275 option.setKind(mcld::ZOption::Origin);
276 mLDConfig->options().addZOption(option);
277 }
278 }
279
addWrap(const std::string & pWrapSymbol)280 void LinkerConfig::addWrap(const std::string &pWrapSymbol) {
281 bool exist = false;
282
283 // Add wname -> __wrap_wname.
284 mcld::StringEntry<llvm::StringRef>* to_wrap =
285 mLDScript->renameMap().insert(pWrapSymbol, exist);
286
287 std::string to_wrap_str = "__wrap_" + pWrapSymbol;
288 to_wrap->setValue(to_wrap_str);
289
290 if (exist) {
291 mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str;
292 }
293
294 // Add __real_wname -> wname.
295 std::string from_real_str = "__real_" + pWrapSymbol;
296 mcld::StringEntry<llvm::StringRef>* from_real =
297 mLDScript->renameMap().insert(from_real_str, exist);
298 from_real->setValue(pWrapSymbol);
299
300 if (exist) {
301 mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str;
302 }
303
304 return;
305 }
306
addPortable(const std::string & pPortableSymbol)307 void LinkerConfig::addPortable(const std::string &pPortableSymbol) {
308 bool exist = false;
309
310 // Add pname -> pname_portable.
311 mcld::StringEntry<llvm::StringRef>* to_port =
312 mLDScript->renameMap().insert(pPortableSymbol, exist);
313
314 std::string to_port_str = pPortableSymbol + "_portable";
315 to_port->setValue(to_port_str);
316
317 if (exist) {
318 mcld::warning(mcld::diag::rewrap) << pPortableSymbol << to_port_str;
319 }
320
321 // Add __real_pname -> pname.
322 std::string from_real_str = "__real_" + pPortableSymbol;
323 mcld::StringEntry<llvm::StringRef>* from_real =
324 mLDScript->renameMap().insert(from_real_str, exist);
325
326 from_real->setValue(pPortableSymbol);
327
328 if (exist) {
329 mcld::warning(mcld::diag::rewrap) << pPortableSymbol << from_real_str;
330 }
331
332 return;
333 }
334
addSearchDir(const std::string & pDirPath)335 void LinkerConfig::addSearchDir(const std::string &pDirPath) {
336 // SearchDirs will remove the created MCLDDirectory.
337 if (!mLDScript->directories().insert(pDirPath)) {
338 mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
339 }
340 }
341