• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- PositionalOptions.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 #include <mcld/PositionalOptions.h>
10 #include <mcld/LinkerConfig.h>
11 #include <mcld/LinkerScript.h>
12 #include <mcld/MC/InputAction.h>
13 #include <mcld/MC/CommandAction.h>
14 #include <mcld/MC/FileAction.h>
15 #include <mcld/Support/MsgHandling.h>
16 
17 namespace {
18 
19 //===----------------------------------------------------------------------===//
20 // Normal input files
21 //===----------------------------------------------------------------------===//
22 llvm::cl::list<mcld::sys::fs::Path> ArgInputObjectFiles(llvm::cl::Positional,
23   llvm::cl::desc("[input object files]"),
24   llvm::cl::ZeroOrMore);
25 
26 // --script is an alias, but cl::alias doesn't work correctly with cl::list.
27 llvm::cl::list<std::string> ArgLinkerScript("T",
28   llvm::cl::ZeroOrMore,
29   llvm::cl::desc("Linker script"),
30   llvm::cl::value_desc("file"));
31 
32 //===----------------------------------------------------------------------===//
33 // Namespecs
34 //===----------------------------------------------------------------------===//
35 llvm::cl::list<std::string> ArgNameSpecList("l",
36   llvm::cl::ZeroOrMore,
37   llvm::cl::desc("Add the archive or object file specified by namespec to\n"
38                  "the list of files to link."),
39   llvm::cl::value_desc("namespec"),
40   llvm::cl::Prefix);
41 
42 llvm::cl::alias ArgNameSpecListAlias("library",
43   llvm::cl::desc("alias for -l"),
44   llvm::cl::aliasopt(ArgNameSpecList));
45 
46 //===----------------------------------------------------------------------===//
47 // Attributes
48 //===----------------------------------------------------------------------===//
49 llvm::cl::list<bool> ArgWholeArchiveList("whole-archive",
50   llvm::cl::ValueDisallowed,
51   llvm::cl::desc("For each archive mentioned on the command line after\n"
52                  "the --whole-archive option, include all object files\n"
53                  "in the archive."));
54 
55 llvm::cl::list<bool> ArgNoWholeArchiveList("no-whole-archive",
56   llvm::cl::ValueDisallowed,
57   llvm::cl::desc("Turn off the effect of the --whole-archive option for\n"
58                  "subsequent archive files."));
59 
60 llvm::cl::list<bool> ArgAsNeededList("as-needed",
61   llvm::cl::ValueDisallowed,
62   llvm::cl::desc("This option affects ELF DT_NEEDED tags for dynamic\n"
63                  "libraries mentioned on the command line after the\n"
64                  "--as-needed option."));
65 
66 llvm::cl::list<bool> ArgNoAsNeededList("no-as-needed",
67   llvm::cl::ValueDisallowed,
68   llvm::cl::desc("Turn off the effect of the --as-needed option for\n"
69                  "subsequent dynamic libraries"));
70 
71 llvm::cl::list<bool> ArgAddNeededList("add-needed",
72   llvm::cl::ValueDisallowed,
73   llvm::cl::desc("--add-needed causes DT_NEEDED tags are always\n"
74                  "emitted for those libraries from DT_NEEDED tags.\n"
75                  "This is the default behavior."));
76 
77 llvm::cl::list<bool> ArgNoAddNeededList("no-add-needed",
78   llvm::cl::ValueDisallowed,
79   llvm::cl::desc("--no-add-needed causes DT_NEEDED tags will never be\n"
80                  "emitted for those libraries from DT_NEEDED tags"));
81 
82 llvm::cl::list<bool> ArgBDynamicList("Bdynamic",
83   llvm::cl::ValueDisallowed,
84   llvm::cl::desc("Link against dynamic library"));
85 
86 llvm::cl::alias ArgBDynamicListAlias1("dy",
87   llvm::cl::desc("alias for --Bdynamic"),
88   llvm::cl::aliasopt(ArgBDynamicList));
89 
90 llvm::cl::alias ArgBDynamicListAlias2("call_shared",
91   llvm::cl::desc("alias for --Bdynamic"),
92   llvm::cl::aliasopt(ArgBDynamicList));
93 
94 llvm::cl::list<bool> ArgBStaticList("Bstatic",
95   llvm::cl::ValueDisallowed,
96   llvm::cl::desc("Link against static library"));
97 
98 llvm::cl::alias ArgBStaticListAlias1("dn",
99   llvm::cl::desc("alias for --Bstatic"),
100   llvm::cl::aliasopt(ArgBStaticList));
101 
102 llvm::cl::alias ArgBStaticListAlias2("static",
103   llvm::cl::desc("alias for --Bstatic"),
104   llvm::cl::aliasopt(ArgBStaticList));
105 
106 llvm::cl::alias ArgBStaticListAlias3("non_shared",
107   llvm::cl::desc("alias for --Bstatic"),
108   llvm::cl::aliasopt(ArgBStaticList));
109 
110 //===----------------------------------------------------------------------===//
111 // Groups
112 //===----------------------------------------------------------------------===//
113 llvm::cl::list<bool> ArgStartGroupList("start-group",
114   llvm::cl::ValueDisallowed,
115   llvm::cl::desc("start to record a group of archives"));
116 
117 llvm::cl::alias ArgStartGroupListAlias("(",
118   llvm::cl::desc("alias for --start-group"),
119   llvm::cl::aliasopt(ArgStartGroupList));
120 
121 llvm::cl::list<bool> ArgEndGroupList("end-group",
122   llvm::cl::ValueDisallowed,
123   llvm::cl::desc("stop recording a group of archives"));
124 
125 llvm::cl::alias ArgEndGroupListAlias(")",
126   llvm::cl::desc("alias for --end-group"),
127   llvm::cl::aliasopt(ArgEndGroupList));
128 
129 //===----------------------------------------------------------------------===//
130 // --defsym
131 //===----------------------------------------------------------------------===//
132 llvm::cl::list<std::string> ArgDefSymList("defsym",
133   llvm::cl::ZeroOrMore,
134   llvm::cl::desc("Define a symbol"),
135   llvm::cl::value_desc("symbol=expression"));
136 
137 //===----------------------------------------------------------------------===//
138 // Help Functions
139 //===----------------------------------------------------------------------===//
140 inline bool
CompareAction(const mcld::InputAction * X,const mcld::InputAction * Y)141 CompareAction(const mcld::InputAction* X, const mcld::InputAction* Y)
142 {
143   return (X->position() < Y->position());
144 }
145 
146 } // anonymous namespace
147 
148 using namespace mcld;
149 
150 //===----------------------------------------------------------------------===//
151 // PositionalOptions
152 //===----------------------------------------------------------------------===//
PositionalOptions()153 PositionalOptions::PositionalOptions()
154   : m_InputObjectFiles(ArgInputObjectFiles),
155     m_LinkerScript(ArgLinkerScript),
156     m_NameSpecList(ArgNameSpecList),
157     m_WholeArchiveList(ArgWholeArchiveList),
158     m_NoWholeArchiveList(ArgNoWholeArchiveList),
159     m_AsNeededList(ArgAsNeededList),
160     m_NoAsNeededList(ArgNoAsNeededList),
161     m_AddNeededList(ArgAddNeededList),
162     m_NoAddNeededList(ArgNoAddNeededList),
163     m_BDynamicList(ArgBDynamicList),
164     m_BStaticList(ArgBStaticList),
165     m_StartGroupList(ArgStartGroupList),
166     m_EndGroupList(ArgEndGroupList),
167     m_DefSymList(ArgDefSymList) {
168 }
169 
numOfActions() const170 size_t PositionalOptions::numOfActions() const
171 {
172   return m_InputObjectFiles.size() +
173          m_LinkerScript.size() +
174          m_NameSpecList.size() +
175          m_WholeArchiveList.size() +
176          m_NoWholeArchiveList.size() +
177          m_AsNeededList.size() +
178          m_NoAsNeededList.size() +
179          m_AddNeededList.size() +
180          m_NoAddNeededList.size() +
181          m_BDynamicList.size() +
182          m_BStaticList.size() +
183          m_StartGroupList.size() +
184          m_EndGroupList.size() +
185          m_DefSymList.size();
186 }
187 
numOfInputs() const188 size_t PositionalOptions::numOfInputs() const
189 {
190   return (m_InputObjectFiles.size() +
191           m_LinkerScript.size() +
192           m_NameSpecList.size());
193 }
194 
parse(std::vector<InputAction * > & pActions,const LinkerConfig & pConfig,const LinkerScript & pScript)195 bool PositionalOptions::parse(std::vector<InputAction*>& pActions,
196                               const LinkerConfig& pConfig,
197                               const LinkerScript& pScript)
198 {
199   if (0 == numOfInputs()) {
200     fatal(diag::err_no_inputs);
201     return false;
202   }
203 
204   pActions.reserve(numOfActions());
205 
206   // -T/--script
207   // FIXME:
208   llvm::cl::list<std::string>::iterator sp;
209   llvm::cl::list<std::string>::iterator spEnd = m_LinkerScript.end();
210   for (sp = m_LinkerScript.begin(); sp != spEnd; ++sp) {
211     pActions.push_back(new ScriptAction(0x0,
212                                        *sp,
213                                        ScriptFile::LDScript,
214                                        pScript.directories()));
215     pActions.push_back(new ContextAction(0x0));
216     pActions.push_back(new MemoryAreaAction(0x0, FileHandle::ReadOnly));
217   }
218 
219   // --defsym
220   llvm::cl::list<std::string>::iterator defsym, dsBegin, dsEnd;
221   dsBegin = m_DefSymList.begin();
222   dsEnd = m_DefSymList.end();
223   for (defsym = dsBegin; defsym != dsEnd; ++defsym) {
224     unsigned int pos = m_DefSymList.getPosition(defsym - dsBegin);
225     pActions.push_back(new DefSymAction(pos, *defsym));
226   }
227 
228   // set input
229   llvm::cl::list<mcld::sys::fs::Path>::iterator input, inBegin, inEnd;
230   inBegin = m_InputObjectFiles.begin();
231   inEnd = m_InputObjectFiles.end();
232   for (input = inBegin; input != inEnd; ++input) {
233     unsigned int pos = m_InputObjectFiles.getPosition(input - inBegin);
234     pActions.push_back(new InputFileAction(pos, *input));
235     pActions.push_back(new ContextAction(pos));
236     pActions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
237   }
238 
239   // set -l[namespec]
240   llvm::cl::list<std::string>::iterator namespec, nsBegin, nsEnd;
241   nsBegin = m_NameSpecList.begin();
242   nsEnd = m_NameSpecList.end();
243   for (namespec = nsBegin; namespec != nsEnd; ++namespec) {
244     unsigned int pos = m_NameSpecList.getPosition(namespec - nsBegin);
245     pActions.push_back(new NamespecAction(pos, *namespec,
246                                           pScript.directories()));
247     pActions.push_back(new ContextAction(pos));
248     pActions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
249   }
250 
251   // set --whole-archive
252   llvm::cl::list<bool>::iterator attr, attrBegin, attrEnd;
253   attrBegin = m_WholeArchiveList.begin();
254   attrEnd   = m_WholeArchiveList.end();
255   for (attr = attrBegin; attr != attrEnd; ++attr) {
256     unsigned int pos = m_WholeArchiveList.getPosition(attr - attrBegin);
257     pActions.push_back(new WholeArchiveAction(pos));
258   }
259 
260   // set --no-whole-archive
261   attrBegin = m_NoWholeArchiveList.begin();
262   attrEnd   = m_NoWholeArchiveList.end();
263   for (attr = attrBegin; attr != attrEnd; ++attr) {
264     unsigned int pos = m_NoWholeArchiveList.getPosition(attr - attrBegin);
265     pActions.push_back(new NoWholeArchiveAction(pos));
266   }
267 
268   // set --as-needed
269   attrBegin = m_AsNeededList.begin();
270   attrEnd   = m_AsNeededList.end();
271   for (attr = attrBegin; attr != attrEnd; ++attr) {
272     unsigned int pos = m_AsNeededList.getPosition(attr - attrBegin);
273     pActions.push_back(new AsNeededAction(pos));
274   }
275 
276   // set --no-as-needed
277   attrBegin = m_NoAsNeededList.begin();
278   attrEnd   = m_NoAsNeededList.end();
279   for (attr = attrBegin; attr != attrEnd; ++attr) {
280     unsigned int pos = m_NoAsNeededList.getPosition(attr - attrBegin);
281     pActions.push_back(new NoAsNeededAction(pos));
282   }
283 
284   // set --add--needed
285   attrBegin = m_AddNeededList.begin();
286   attrEnd   = m_AddNeededList.end();
287   for (attr = attrBegin; attr != attrEnd; ++attr) {
288     unsigned int pos = m_AddNeededList.getPosition(attr - attrBegin);
289     pActions.push_back(new AddNeededAction(pos));
290   }
291 
292   // set --no-add--needed
293   attrBegin = m_NoAddNeededList.begin();
294   attrEnd   = m_NoAddNeededList.end();
295   for (attr = attrBegin; attr != attrEnd; ++attr) {
296     unsigned int pos = m_NoAddNeededList.getPosition(attr - attrBegin);
297     pActions.push_back(new NoAddNeededAction(pos));
298   }
299 
300   // set --Bdynamic
301   attrBegin = m_BDynamicList.begin();
302   attrEnd   = m_BDynamicList.end();
303   for (attr = attrBegin; attr != attrEnd; ++attr) {
304     unsigned int pos = m_BDynamicList.getPosition(attr - attrBegin);
305     pActions.push_back(new BDynamicAction(pos));
306   }
307 
308   // set --Bstatic
309   attrBegin = m_BStaticList.begin();
310   attrEnd   = m_BStaticList.end();
311   for (attr = attrBegin; attr != attrEnd; ++attr) {
312     unsigned int pos = m_BStaticList.getPosition(attr - attrBegin);
313     pActions.push_back(new BStaticAction(pos));
314   }
315 
316   // set --start-group
317   llvm::cl::list<bool>::iterator group, gsBegin, gsEnd;
318   gsBegin = m_StartGroupList.begin();
319   gsEnd   = m_StartGroupList.end();
320   for (group = gsBegin; group != gsEnd; ++group) {
321     unsigned int pos = m_StartGroupList.getPosition(group - gsBegin);
322     pActions.push_back(new StartGroupAction(pos));
323   }
324 
325   // set --end-group
326   gsBegin = m_EndGroupList.begin();
327   gsEnd   = m_EndGroupList.end();
328   for (group = gsBegin; group != gsEnd; ++group) {
329     unsigned int pos = m_EndGroupList.getPosition(group - gsBegin);
330     pActions.push_back(new EndGroupAction(pos));
331   }
332 
333   // stable sort
334   std::stable_sort(pActions.begin(), pActions.end(), CompareAction);
335 
336   return true;
337 }
338 
339