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