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