• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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