• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- MCLinker.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 // This file implements the MCLinker class.
11 //
12 //===----------------------------------------------------------------------===//
13 #include <mcld/CodeGen/MCLinker.h>
14 
15 #include <mcld/Module.h>
16 #include <mcld/LinkerConfig.h>
17 #include <mcld/LinkerScript.h>
18 #include <mcld/InputTree.h>
19 #include <mcld/Linker.h>
20 #include <mcld/IRBuilder.h>
21 #include <mcld/MC/InputBuilder.h>
22 #include <mcld/MC/FileAction.h>
23 #include <mcld/MC/CommandAction.h>
24 #include <mcld/Object/ObjectLinker.h>
25 #include <mcld/Support/CommandLine.h>
26 #include <mcld/Support/FileSystem.h>
27 #include <mcld/Support/MsgHandling.h>
28 #include <mcld/Support/FileHandle.h>
29 #include <mcld/Support/raw_ostream.h>
30 
31 #include <llvm/IR/Module.h>
32 #include <llvm/Support/CommandLine.h>
33 
34 #include <algorithm>
35 #include <vector>
36 #include <string>
37 
38 using namespace mcld;
39 using namespace llvm;
40 
41 char MCLinker::m_ID = 0;
42 
43 //===----------------------------------------------------------------------===//
44 // Help Functions
45 //===----------------------------------------------------------------------===//
CompareAction(const InputAction * X,const InputAction * Y)46 static inline bool CompareAction(const InputAction* X, const InputAction* Y)
47 {
48   return (X->position() < Y->position());
49 }
50 
51 //===----------------------------------------------------------------------===//
52 // Positional Options
53 // There are four kinds of positional options:
54 //   1. Inputs, object files, such as /tmp/XXXX.o
55 //   2. Namespecs, short names of libraries. A namespec may refer to an archive
56 //      or a shared library. For example, -lm.
57 //   3. Attributes of inputs. Attributes describe inputs appears after them.
58 //      For example, --as-needed and --whole-archive.
59 //   4. Groups. A Group is a set of archives. Linkers repeatedly read archives
60 //      in groups until there is no new undefined symbols.
61 //   5. Bitcode. Bitcode is a kind of object files. MCLinker compiles it to
62 //      object file first, then link it as a object file. (Bitcode is recorded
63 //      in BitcodeOption, not be read by LLVM Command Line library.)
64 //===----------------------------------------------------------------------===//
65 // Inputs
66 //===----------------------------------------------------------------------===//
67 static cl::list<mcld::sys::fs::Path>
68 ArgInputObjectFiles(cl::Positional,
69                     cl::desc("[input object files]"),
70                     cl::ZeroOrMore);
71 
72 //===----------------------------------------------------------------------===//
73 // Namespecs
74 //===----------------------------------------------------------------------===//
75 static cl::list<std::string>
76 ArgNameSpecList("l",
77             cl::ZeroOrMore,
78             cl::desc("Add the archive or object file specified by namespec to "
79                      "the list of files to link."),
80             cl::value_desc("namespec"),
81             cl::Prefix);
82 
83 static cl::alias
84 ArgNameSpecListAlias("library",
85                  cl::desc("alias for -l"),
86                  cl::aliasopt(ArgNameSpecList));
87 
88 //===----------------------------------------------------------------------===//
89 // Attributes
90 //===----------------------------------------------------------------------===//
91 static cl::list<bool>
92 ArgWholeArchiveList("whole-archive",
93                cl::ValueDisallowed,
94                cl::desc("For each archive mentioned on the command line after "
95                         "the --whole-archive option, include all object files "
96                         "in the archive."));
97 
98 static cl::list<bool>
99 ArgNoWholeArchiveList("no-whole-archive",
100                cl::ValueDisallowed,
101                cl::desc("Turn off the effect of the --whole-archive option for "
102                         "subsequent archive files."));
103 
104 static cl::list<bool>
105 ArgAsNeededList("as-needed",
106                cl::ValueDisallowed,
107                cl::desc("This option affects ELF DT_NEEDED tags for dynamic "
108                         "libraries mentioned on the command line after the "
109                         "--as-needed option."));
110 
111 static cl::list<bool>
112 ArgNoAsNeededList("no-as-needed",
113                cl::ValueDisallowed,
114                cl::desc("Turn off the effect of the --as-needed option for "
115                         "subsequent dynamic libraries"));
116 
117 static cl::list<bool>
118 ArgAddNeededList("add-needed",
119                 cl::ValueDisallowed,
120                 cl::desc("--add-needed causes DT_NEEDED tags are always "
121                          "emitted for those libraries from DT_NEEDED tags. "
122                          "This is the default behavior."));
123 
124 static cl::list<bool>
125 ArgNoAddNeededList("no-add-needed",
126                 cl::ValueDisallowed,
127                 cl::desc("--no-add-needed causes DT_NEEDED tags will never be "
128                          "emitted for those libraries from DT_NEEDED tags"));
129 
130 static cl::list<bool>
131 ArgBDynamicList("Bdynamic",
132                 cl::ValueDisallowed,
133                 cl::desc("Link against dynamic library"));
134 
135 static cl::alias
136 ArgBDynamicListAlias1("dy",
137                 cl::desc("alias for --Bdynamic"),
138                 cl::aliasopt(ArgBDynamicList));
139 
140 static cl::alias
141 ArgBDynamicListAlias2("call_shared",
142                 cl::desc("alias for --Bdynamic"),
143                 cl::aliasopt(ArgBDynamicList));
144 
145 static cl::list<bool>
146 ArgBStaticList("Bstatic",
147                 cl::ValueDisallowed,
148                 cl::desc("Link against static library"));
149 
150 static cl::alias
151 ArgBStaticListAlias1("dn",
152                 cl::desc("alias for --Bstatic"),
153                 cl::aliasopt(ArgBStaticList));
154 
155 static cl::alias
156 ArgBStaticListAlias2("static",
157                 cl::desc("alias for --Bstatic"),
158                 cl::aliasopt(ArgBStaticList));
159 
160 static cl::alias
161 ArgBStaticListAlias3("non_shared",
162                 cl::desc("alias for --Bstatic"),
163                 cl::aliasopt(ArgBStaticList));
164 
165 //===----------------------------------------------------------------------===//
166 // Groups
167 //===----------------------------------------------------------------------===//
168 static cl::list<bool>
169 ArgStartGroupList("start-group",
170                   cl::ValueDisallowed,
171                   cl::desc("start to record a group of archives"));
172 
173 static cl::alias
174 ArgStartGroupListAlias("(",
175                        cl::desc("alias for --start-group"),
176                        cl::aliasopt(ArgStartGroupList));
177 
178 static cl::list<bool>
179 ArgEndGroupList("end-group",
180                 cl::ValueDisallowed,
181                 cl::desc("stop recording a group of archives"));
182 
183 static cl::alias
184 ArgEndGroupListAlias(")",
185                      cl::desc("alias for --end-group"),
186                      cl::aliasopt(ArgEndGroupList));
187 
188 //===----------------------------------------------------------------------===//
189 // --defsym
190 //===----------------------------------------------------------------------===//
191 static cl::list<std::string>
192 ArgDefSymList("defsym",
193               cl::ZeroOrMore,
194               cl::desc("Define a symbol"),
195               cl::value_desc("symbol=expression"));
196 
197 //===----------------------------------------------------------------------===//
198 // MCLinker
199 //===----------------------------------------------------------------------===//
MCLinker(LinkerConfig & pConfig,mcld::Module & pModule,FileHandle & pFileHandle)200 MCLinker::MCLinker(LinkerConfig& pConfig,
201                    mcld::Module& pModule,
202                    FileHandle& pFileHandle)
203   : MachineFunctionPass(m_ID),
204     m_Config(pConfig),
205     m_Module(pModule),
206     m_FileHandle(pFileHandle),
207     m_pBuilder(NULL),
208     m_pLinker(NULL) {
209 }
210 
~MCLinker()211 MCLinker::~MCLinker()
212 {
213   delete m_pLinker;
214   delete m_pBuilder;
215 }
216 
doInitialization(llvm::Module & pM)217 bool MCLinker::doInitialization(llvm::Module &pM)
218 {
219   // Now, all input arguments are prepared well, send it into ObjectLinker
220   m_pLinker = new Linker();
221 
222   if (!m_pLinker->emulate(m_Module.getScript(), m_Config))
223     return false;
224 
225   m_pBuilder = new IRBuilder(m_Module, m_Config);
226 
227   initializeInputTree(*m_pBuilder);
228 
229   return true;
230 }
231 
doFinalization(llvm::Module & pM)232 bool MCLinker::doFinalization(llvm::Module &pM)
233 {
234   if (!m_pLinker->link(m_Module, *m_pBuilder))
235     return true;
236 
237   if (!m_pLinker->emit(m_Module, m_FileHandle.handler()))
238     return true;
239 
240   return false;
241 }
242 
runOnMachineFunction(MachineFunction & pF)243 bool MCLinker::runOnMachineFunction(MachineFunction& pF)
244 {
245   // basically, linkers do nothing during function is generated.
246   return false;
247 }
248 
initializeInputTree(IRBuilder & pBuilder)249 void MCLinker::initializeInputTree(IRBuilder& pBuilder)
250 {
251   if (0 == ArgInputObjectFiles.size() &&
252       0 == ArgNameSpecList.size() &&
253       !m_Config.bitcode().hasDefined()) {
254     fatal(diag::err_no_inputs);
255     return;
256   }
257 
258   size_t num_actions = ArgInputObjectFiles.size() +
259                        ArgNameSpecList.size() +
260                        ArgWholeArchiveList.size() +
261                        ArgNoWholeArchiveList.size() +
262                        ArgAsNeededList.size() +
263                        ArgNoAsNeededList.size() +
264                        ArgAddNeededList.size() +
265                        ArgNoAddNeededList.size() +
266                        ArgBDynamicList.size() +
267                        ArgBStaticList.size() +
268                        ArgStartGroupList.size() +
269                        ArgEndGroupList.size() +
270                        ArgDefSymList.size() +
271                        1; // bitcode
272   std::vector<InputAction*> actions;
273   actions.reserve(num_actions);
274 
275   // -----  scripts  ----- //
276   /// -T
277   if (!m_Config.options().getScriptList().empty()) {
278     GeneralOptions::const_script_iterator ii, ie = m_Config.options().script_end();
279     for (ii = m_Config.options().script_begin(); ii != ie; ++ii) {
280       actions.push_back(new ScriptAction(0x0,
281                                          *ii,
282                                          ScriptFile::LDScript,
283                                          m_Module.getScript().directories()));
284       actions.push_back(new ContextAction(0x0));
285       actions.push_back(new MemoryAreaAction(0x0, FileHandle::ReadOnly));
286     }
287   }
288 
289   /// --defsym
290   cl::list<std::string>::iterator defsym, dsBegin, dsEnd;
291   dsBegin = ArgDefSymList.begin();
292   dsEnd = ArgDefSymList.end();
293   for (defsym = dsBegin; defsym != dsEnd; ++defsym) {
294     unsigned int pos = ArgDefSymList.getPosition(defsym - dsBegin);
295     actions.push_back(new DefSymAction(pos, *defsym));
296   }
297 
298   // -----  inputs  ----- //
299   cl::list<mcld::sys::fs::Path>::iterator input, inBegin, inEnd;
300   inBegin = ArgInputObjectFiles.begin();
301   inEnd = ArgInputObjectFiles.end();
302   for (input = inBegin; input != inEnd; ++input) {
303     unsigned int pos = ArgInputObjectFiles.getPosition(input - inBegin);
304     actions.push_back(new InputFileAction(pos, *input));
305     actions.push_back(new ContextAction(pos));
306     actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
307   }
308 
309   // -----  namespecs  ----- //
310   cl::list<std::string>::iterator namespec, nsBegin, nsEnd;
311   nsBegin = ArgNameSpecList.begin();
312   nsEnd = ArgNameSpecList.end();
313   for (namespec = nsBegin; namespec != nsEnd; ++namespec) {
314     unsigned int pos = ArgNameSpecList.getPosition(namespec - nsBegin);
315     actions.push_back(new NamespecAction(pos, *namespec,
316                                          m_Module.getScript().directories()));
317     actions.push_back(new ContextAction(pos));
318     actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
319   }
320 
321   // -----  attributes  ----- //
322   /// --whole-archive
323   cl::list<bool>::iterator attr, attrBegin, attrEnd;
324   attrBegin = ArgWholeArchiveList.begin();
325   attrEnd   = ArgWholeArchiveList.end();
326   for (attr = attrBegin; attr != attrEnd; ++attr) {
327     unsigned int pos = ArgWholeArchiveList.getPosition(attr - attrBegin);
328     actions.push_back(new WholeArchiveAction(pos));
329   }
330 
331   /// --no-whole-archive
332   attrBegin = ArgNoWholeArchiveList.begin();
333   attrEnd   = ArgNoWholeArchiveList.end();
334   for (attr = attrBegin; attr != attrEnd; ++attr) {
335     unsigned int pos = ArgNoWholeArchiveList.getPosition(attr - attrBegin);
336     actions.push_back(new NoWholeArchiveAction(pos));
337   }
338 
339   /// --as-needed
340   attrBegin = ArgAsNeededList.begin();
341   attrEnd   = ArgAsNeededList.end();
342   for (attr = attrBegin; attr != attrEnd; ++attr) {
343     unsigned int pos = ArgAsNeededList.getPosition(attr - attrBegin);
344     actions.push_back(new AsNeededAction(pos));
345   }
346 
347   /// --no-as-needed
348   attrBegin = ArgNoAsNeededList.begin();
349   attrEnd   = ArgNoAsNeededList.end();
350   for (attr = attrBegin; attr != attrEnd; ++attr) {
351     unsigned int pos = ArgNoAsNeededList.getPosition(attr - attrBegin);
352     actions.push_back(new NoAsNeededAction(pos));
353   }
354 
355   /// --add--needed
356   attrBegin = ArgAddNeededList.begin();
357   attrEnd   = ArgAddNeededList.end();
358   for (attr = attrBegin; attr != attrEnd; ++attr) {
359     unsigned int pos = ArgAddNeededList.getPosition(attr - attrBegin);
360     actions.push_back(new AddNeededAction(pos));
361   }
362 
363   /// --no-add--needed
364   attrBegin = ArgNoAddNeededList.begin();
365   attrEnd   = ArgNoAddNeededList.end();
366   for (attr = attrBegin; attr != attrEnd; ++attr) {
367     unsigned int pos = ArgNoAddNeededList.getPosition(attr - attrBegin);
368     actions.push_back(new NoAddNeededAction(pos));
369   }
370 
371   /// --Bdynamic
372   attrBegin = ArgBDynamicList.begin();
373   attrEnd   = ArgBDynamicList.end();
374   for (attr = attrBegin; attr != attrEnd; ++attr) {
375     unsigned int pos = ArgBDynamicList.getPosition(attr - attrBegin);
376     actions.push_back(new BDynamicAction(pos));
377   }
378 
379   /// --Bstatic
380   attrBegin = ArgBStaticList.begin();
381   attrEnd   = ArgBStaticList.end();
382   for (attr = attrBegin; attr != attrEnd; ++attr) {
383     unsigned int pos = ArgBStaticList.getPosition(attr - attrBegin);
384     actions.push_back(new BStaticAction(pos));
385   }
386 
387   // -----  groups  ----- //
388   /// --start-group
389   cl::list<bool>::iterator group, gsBegin, gsEnd;
390   gsBegin = ArgStartGroupList.begin();
391   gsEnd   = ArgStartGroupList.end();
392   for (group = gsBegin; group != gsEnd; ++group) {
393     unsigned int pos = ArgStartGroupList.getPosition(group - gsBegin);
394     actions.push_back(new StartGroupAction(pos));
395   }
396 
397   /// --end-group
398   gsBegin = ArgEndGroupList.begin();
399   gsEnd   = ArgEndGroupList.end();
400   for (group = gsBegin; group != gsEnd; ++group) {
401     unsigned int pos = ArgEndGroupList.getPosition(group - gsBegin);
402     actions.push_back(new EndGroupAction(pos));
403   }
404 
405   // -----  bitcode  ----- //
406   if (m_Config.bitcode().hasDefined()) {
407     actions.push_back(new BitcodeAction(m_Config.bitcode().getPosition(),
408                                         m_Config.bitcode().getPath()));
409   }
410 
411   // stable sort
412   std::stable_sort(actions.begin(), actions.end(), CompareAction);
413 
414   // build up input tree
415   std::vector<InputAction*>::iterator action, actionEnd = actions.end();
416   for (action = actions.begin(); action != actionEnd; ++action) {
417     (*action)->activate(pBuilder.getInputBuilder());
418     delete *action;
419   }
420 
421   if (pBuilder.getInputBuilder().isInGroup())
422     report_fatal_error("no matched --start-group and --end-group");
423 }
424 
425