• 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/InputTree.h>
18 #include <mcld/Linker.h>
19 #include <mcld/IRBuilder.h>
20 #include <mcld/MC/InputBuilder.h>
21 #include <mcld/MC/FileAction.h>
22 #include <mcld/MC/CommandAction.h>
23 #include <mcld/Object/ObjectLinker.h>
24 #include <mcld/Support/CommandLine.h>
25 #include <mcld/Support/FileSystem.h>
26 #include <mcld/Support/MsgHandling.h>
27 #include <mcld/Support/FileHandle.h>
28 #include <mcld/Support/raw_ostream.h>
29 #include <mcld/Support/MemoryArea.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 // MCLinker
190 //===----------------------------------------------------------------------===//
MCLinker(LinkerConfig & pConfig,mcld::Module & pModule,MemoryArea & pOutput)191 MCLinker::MCLinker(LinkerConfig& pConfig,
192                    mcld::Module& pModule,
193                    MemoryArea& pOutput)
194   : MachineFunctionPass(m_ID),
195     m_Config(pConfig),
196     m_Module(pModule),
197     m_Output(pOutput),
198     m_pBuilder(NULL),
199     m_pLinker(NULL) {
200 }
201 
~MCLinker()202 MCLinker::~MCLinker()
203 {
204   delete m_pLinker;
205   delete m_pBuilder;
206 }
207 
doInitialization(llvm::Module & pM)208 bool MCLinker::doInitialization(llvm::Module &pM)
209 {
210   // Now, all input arguments are prepared well, send it into ObjectLinker
211   m_pLinker = new Linker();
212 
213   if (!m_pLinker->config(m_Config))
214     return false;
215 
216   m_pBuilder = new IRBuilder(m_Module, m_Config);
217 
218   initializeInputTree(*m_pBuilder);
219 
220   return true;
221 }
222 
doFinalization(llvm::Module & pM)223 bool MCLinker::doFinalization(llvm::Module &pM)
224 {
225   if (!m_pLinker->link(m_Module, *m_pBuilder))
226     return true;
227 
228   if (!m_pLinker->emit(m_Output))
229     return true;
230 
231   return false;
232 }
233 
runOnMachineFunction(MachineFunction & pF)234 bool MCLinker::runOnMachineFunction(MachineFunction& pF)
235 {
236   // basically, linkers do nothing during function is generated.
237   return false;
238 }
239 
initializeInputTree(IRBuilder & pBuilder)240 void MCLinker::initializeInputTree(IRBuilder& pBuilder)
241 {
242   if (0 == ArgInputObjectFiles.size() &&
243       0 == ArgNameSpecList.size() &&
244       !m_Config.bitcode().hasDefined()) {
245     fatal(diag::err_no_inputs);
246     return;
247   }
248 
249   size_t num_actions = ArgInputObjectFiles.size() +
250                        ArgNameSpecList.size() +
251                        ArgWholeArchiveList.size() +
252                        ArgNoWholeArchiveList.size() +
253                        ArgAsNeededList.size() +
254                        ArgNoAsNeededList.size() +
255                        ArgAddNeededList.size() +
256                        ArgNoAddNeededList.size() +
257                        ArgBDynamicList.size() +
258                        ArgBStaticList.size() +
259                        ArgStartGroupList.size() +
260                        ArgEndGroupList.size() +
261                        1; // bitcode
262   std::vector<InputAction*> actions;
263   actions.reserve(num_actions);
264 
265   // -----  inputs  ----- //
266   cl::list<mcld::sys::fs::Path>::iterator input, inBegin, inEnd;
267   inBegin = ArgInputObjectFiles.begin();
268   inEnd = ArgInputObjectFiles.end();
269   for (input = inBegin; input != inEnd; ++input) {
270     unsigned int pos = ArgInputObjectFiles.getPosition(input - inBegin);
271     actions.push_back(new InputFileAction(pos, *input));
272     actions.push_back(new ContextAction(pos));
273     actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
274   }
275 
276   // -----  namespecs  ----- //
277   cl::list<std::string>::iterator namespec, nsBegin, nsEnd;
278   nsBegin = ArgNameSpecList.begin();
279   nsEnd = ArgNameSpecList.end();
280   for (namespec = nsBegin; namespec != nsEnd; ++namespec) {
281     unsigned int pos = ArgNameSpecList.getPosition(namespec - nsBegin);
282     actions.push_back(new NamespecAction(pos, *namespec,
283                                          m_Config.options().directories()));
284     actions.push_back(new ContextAction(pos));
285     actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
286   }
287 
288   // -----  attributes  ----- //
289   /// --whole-archive
290   cl::list<bool>::iterator attr, attrBegin, attrEnd;
291   attrBegin = ArgWholeArchiveList.begin();
292   attrEnd   = ArgWholeArchiveList.end();
293   for (attr = attrBegin; attr != attrEnd; ++attr) {
294     unsigned int pos = ArgWholeArchiveList.getPosition(attr - attrBegin);
295     actions.push_back(new WholeArchiveAction(pos));
296   }
297 
298   /// --no-whole-archive
299   attrBegin = ArgNoWholeArchiveList.begin();
300   attrEnd   = ArgNoWholeArchiveList.end();
301   for (attr = attrBegin; attr != attrEnd; ++attr) {
302     unsigned int pos = ArgNoWholeArchiveList.getPosition(attr - attrBegin);
303     actions.push_back(new NoWholeArchiveAction(pos));
304   }
305 
306   /// --as-needed
307   attrBegin = ArgAsNeededList.begin();
308   attrEnd   = ArgAsNeededList.end();
309   for (attr = attrBegin; attr != attrEnd; ++attr) {
310     unsigned int pos = ArgAsNeededList.getPosition(attr - attrBegin);
311     actions.push_back(new AsNeededAction(pos));
312   }
313 
314   /// --no-as-needed
315   attrBegin = ArgNoAsNeededList.begin();
316   attrEnd   = ArgNoAsNeededList.end();
317   for (attr = attrBegin; attr != attrEnd; ++attr) {
318     unsigned int pos = ArgNoAsNeededList.getPosition(attr - attrBegin);
319     actions.push_back(new NoAsNeededAction(pos));
320   }
321 
322   /// --add--needed
323   attrBegin = ArgAddNeededList.begin();
324   attrEnd   = ArgAddNeededList.end();
325   for (attr = attrBegin; attr != attrEnd; ++attr) {
326     unsigned int pos = ArgAddNeededList.getPosition(attr - attrBegin);
327     actions.push_back(new AddNeededAction(pos));
328   }
329 
330   /// --no-add--needed
331   attrBegin = ArgNoAddNeededList.begin();
332   attrEnd   = ArgNoAddNeededList.end();
333   for (attr = attrBegin; attr != attrEnd; ++attr) {
334     unsigned int pos = ArgNoAddNeededList.getPosition(attr - attrBegin);
335     actions.push_back(new NoAddNeededAction(pos));
336   }
337 
338   /// --Bdynamic
339   attrBegin = ArgBDynamicList.begin();
340   attrEnd   = ArgBDynamicList.end();
341   for (attr = attrBegin; attr != attrEnd; ++attr) {
342     unsigned int pos = ArgBDynamicList.getPosition(attr - attrBegin);
343     actions.push_back(new BDynamicAction(pos));
344   }
345 
346   /// --Bstatic
347   attrBegin = ArgBStaticList.begin();
348   attrEnd   = ArgBStaticList.end();
349   for (attr = attrBegin; attr != attrEnd; ++attr) {
350     unsigned int pos = ArgBStaticList.getPosition(attr - attrBegin);
351     actions.push_back(new BStaticAction(pos));
352   }
353 
354   // -----  groups  ----- //
355   /// --start-group
356   cl::list<bool>::iterator group, gsBegin, gsEnd;
357   gsBegin = ArgStartGroupList.begin();
358   gsEnd   = ArgStartGroupList.end();
359   for (group = gsBegin; group != gsEnd; ++group) {
360     unsigned int pos = ArgStartGroupList.getPosition(group - gsBegin);
361     actions.push_back(new StartGroupAction(pos));
362   }
363 
364   /// --end-group
365   gsBegin = ArgEndGroupList.begin();
366   gsEnd   = ArgEndGroupList.end();
367   for (group = gsBegin; group != gsEnd; ++group) {
368     unsigned int pos = ArgEndGroupList.getPosition(group - gsBegin);
369     actions.push_back(new EndGroupAction(pos));
370   }
371 
372   // -----  bitcode  ----- //
373   if (m_Config.bitcode().hasDefined()) {
374     actions.push_back(new BitcodeAction(m_Config.bitcode().getPosition(),
375                                         m_Config.bitcode().getPath()));
376   }
377 
378   // stable sort
379   std::stable_sort(actions.begin(), actions.end(), CompareAction);
380 
381   // build up input tree
382   std::vector<InputAction*>::iterator action, actionEnd = actions.end();
383   for (action = actions.begin(); action != actionEnd; ++action) {
384     (*action)->activate(pBuilder.getInputBuilder());
385     delete *action;
386   }
387 
388   if (pBuilder.getInputBuilder().isInGroup())
389     report_fatal_error("no matched --start-group and --end-group");
390 }
391 
392