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