1//===- CommandAction.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/MC/CommandAction.h>
10#include <mcld/MC/InputBuilder.h>
11#include <mcld/MC/SearchDirs.h>
12#include <mcld/MC/Attribute.h>
13#include <mcld/Support/MsgHandling.h>
14#include <mcld/Support/FileSystem.h>
15#include <mcld/LinkerConfig.h>
16
17using namespace mcld;
18
19//===----------------------------------------------------------------------===//
20// Derived Positional Option
21//===----------------------------------------------------------------------===//
22// InputFileAction
23//===----------------------------------------------------------------------===//
24InputFileAction::InputFileAction(unsigned int pPosition,
25                                 const sys::fs::Path &pPath)
26  : InputAction(pPosition), m_Path(pPath) {
27}
28
29bool InputFileAction::activate(InputBuilder& pBuilder) const
30{
31  pBuilder.createNode<InputTree::Positional>(path().stem().native(), path());
32  return true;
33}
34
35//===----------------------------------------------------------------------===//
36// NamespecAction
37//===----------------------------------------------------------------------===//
38NamespecAction::NamespecAction(unsigned int pPosition,
39                               const std::string &pNamespec,
40                               const SearchDirs& pSearchDirs)
41  : InputAction(pPosition), m_Namespec(pNamespec), m_SearchDirs(pSearchDirs) {
42}
43
44bool NamespecAction::activate(InputBuilder& pBuilder) const
45{
46  const sys::fs::Path* path = NULL;
47  // find out the real path of the namespec.
48  if (pBuilder.getConstraint().isSharedSystem()) {
49    // In the system with shared object support, we can find both archive
50    // and shared object.
51
52    if (pBuilder.getAttributes().isStatic()) {
53      // with --static, we must search an archive.
54      path = m_SearchDirs.find(namespec(), Input::Archive);
55    }
56    else {
57      // otherwise, with --Bdynamic, we can find either an archive or a
58      // shared object.
59      path = m_SearchDirs.find(namespec(), Input::DynObj);
60    }
61  }
62  else {
63    // In the system without shared object support, we only look for an archive
64    path = m_SearchDirs.find(namespec(), Input::Archive);
65  }
66
67  if (NULL == path) {
68    fatal(diag::err_cannot_find_namespec) << namespec();
69    return false;
70  }
71
72  pBuilder.createNode<InputTree::Positional>(namespec(), *path);
73  return true;
74}
75
76//===----------------------------------------------------------------------===//
77// BitcodeAction
78//===----------------------------------------------------------------------===//
79BitcodeAction::BitcodeAction(unsigned int pPosition, const sys::fs::Path &pPath)
80  : InputAction(pPosition), m_Path(pPath) {
81}
82
83bool BitcodeAction::activate(InputBuilder& pBuilder) const
84{
85  pBuilder.createNode<InputTree::Positional>("bitcode", path(), Input::External);
86  return true;
87}
88
89//===----------------------------------------------------------------------===//
90// StartGroupAction
91//===----------------------------------------------------------------------===//
92StartGroupAction::StartGroupAction(unsigned int pPosition)
93  : InputAction(pPosition) {
94}
95
96bool StartGroupAction::activate(InputBuilder& pBuilder) const
97{
98  if (pBuilder.isInGroup()) {
99    fatal(diag::fatal_forbid_nest_group);
100    return false;
101  }
102  pBuilder.enterGroup();
103  return true;
104}
105
106//===----------------------------------------------------------------------===//
107// EndGroupAction
108//===----------------------------------------------------------------------===//
109EndGroupAction::EndGroupAction(unsigned int pPosition)
110  : InputAction(pPosition) {
111}
112
113bool EndGroupAction::activate(InputBuilder& pBuilder) const
114{
115  pBuilder.exitGroup();
116  return true;
117}
118
119//===----------------------------------------------------------------------===//
120// WholeArchiveAction
121//===----------------------------------------------------------------------===//
122WholeArchiveAction::WholeArchiveAction(unsigned int pPosition)
123  : InputAction(pPosition) {
124}
125
126bool WholeArchiveAction::activate(InputBuilder& pBuilder) const
127{
128  pBuilder.getAttributes().setWholeArchive();
129  return true;
130}
131
132//===----------------------------------------------------------------------===//
133// NoWholeArchiveAction
134//===----------------------------------------------------------------------===//
135NoWholeArchiveAction::NoWholeArchiveAction(unsigned int pPosition)
136  : InputAction(pPosition) {
137}
138
139bool NoWholeArchiveAction::activate(InputBuilder& pBuilder) const
140{
141  pBuilder.getAttributes().unsetWholeArchive();
142  return true;
143}
144
145//===----------------------------------------------------------------------===//
146// AsNeededAction
147//===----------------------------------------------------------------------===//
148AsNeededAction::AsNeededAction(unsigned int pPosition)
149  : InputAction(pPosition) {
150}
151
152bool AsNeededAction::activate(InputBuilder& pBuilder) const
153{
154  pBuilder.getAttributes().setAsNeeded();
155  return true;
156}
157
158//===----------------------------------------------------------------------===//
159// NoAsNeededAction
160//===----------------------------------------------------------------------===//
161NoAsNeededAction::NoAsNeededAction(unsigned int pPosition)
162  : InputAction(pPosition) {
163}
164
165bool NoAsNeededAction::activate(InputBuilder& pBuilder) const
166{
167  pBuilder.getAttributes().unsetAsNeeded();
168  return true;
169}
170
171//===----------------------------------------------------------------------===//
172// AddNeededAction
173//===----------------------------------------------------------------------===//
174AddNeededAction::AddNeededAction(unsigned int pPosition)
175  : InputAction(pPosition) {
176}
177
178bool AddNeededAction::activate(InputBuilder& pBuilder) const
179{
180  pBuilder.getAttributes().setAddNeeded();
181  return true;
182}
183
184//===----------------------------------------------------------------------===//
185// NoAddNeededAction
186//===----------------------------------------------------------------------===//
187NoAddNeededAction::NoAddNeededAction(unsigned int pPosition)
188  : InputAction(pPosition) {
189}
190
191bool NoAddNeededAction::activate(InputBuilder& pBuilder) const
192{
193  pBuilder.getAttributes().unsetAddNeeded();
194  return true;
195}
196
197//===----------------------------------------------------------------------===//
198// BDynamicAction
199//===----------------------------------------------------------------------===//
200BDynamicAction::BDynamicAction(unsigned int pPosition)
201  : InputAction(pPosition) {
202}
203
204bool BDynamicAction::activate(InputBuilder& pBuilder) const
205{
206  pBuilder.getAttributes().setDynamic();
207  return true;
208}
209
210//===----------------------------------------------------------------------===//
211// BStaticAction
212//===----------------------------------------------------------------------===//
213BStaticAction::BStaticAction(unsigned int pPosition)
214  : InputAction(pPosition) {
215}
216
217bool BStaticAction::activate(InputBuilder& pBuilder) const
218{
219  pBuilder.getAttributes().setStatic();
220  return true;
221}
222
223//===----------------------------------------------------------------------===//
224// DefSymAction
225//===----------------------------------------------------------------------===//
226DefSymAction::DefSymAction(unsigned int pPosition, std::string& pAssignment)
227  : InputAction(pPosition), m_Assignment(pAssignment) {
228}
229
230bool DefSymAction::activate(InputBuilder& pBuilder) const
231{
232  pBuilder.createNode<InputTree::Positional>("defsym", "NAN");
233  Input* input = *pBuilder.getCurrentNode();
234  pBuilder.setContext(*input, false);
235
236  m_Assignment.append(";");
237  pBuilder.setMemory(*input, &m_Assignment[0], m_Assignment.size());
238  return true;
239}
240
241//===----------------------------------------------------------------------===//
242// ScriptAction
243//===----------------------------------------------------------------------===//
244ScriptAction::ScriptAction(unsigned int pPosition,
245                           const std::string& pFileName,
246                           ScriptFile::Kind pKind,
247                           const SearchDirs& pSearchDirs)
248  : InputAction(pPosition),
249    m_FileName(pFileName),
250    m_Kind(pKind),
251    m_SearchDirs(pSearchDirs) {
252}
253
254bool ScriptAction::activate(InputBuilder& pBuilder) const
255{
256  sys::fs::Path path(m_FileName);
257
258  if (!exists(path)) {
259    const sys::fs::Path* res = m_SearchDirs.find(m_FileName, Input::Script);
260    if (res == NULL) {
261      switch (m_Kind) {
262      case ScriptFile::LDScript:
263        fatal(diag::err_cannot_find_scriptfile) << "linker script" << m_FileName;
264        break;
265      case ScriptFile::VersionScript:
266        fatal(diag::err_cannot_find_scriptfile) << "version script" << m_FileName;
267        break;
268      case ScriptFile::DynamicList:
269        fatal(diag::err_cannot_find_scriptfile) << "dynamic list" << m_FileName;
270        break;
271      default:
272        break;
273      }
274      return false;
275    }
276    path.assign(res->native());
277  }
278
279  pBuilder.createNode<InputTree::Positional>(path.stem().native(), path);
280
281  return true;
282}
283