1f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===- GroupCmd.cpp -------------------------------------------------------===//
2f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
3f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//                     The MCLinker Project
4f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
5f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// This file is distributed under the University of Illinois Open Source
6f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// License. See LICENSE.TXT for details.
7f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
8f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
9f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/GroupCmd.h>
10f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/StringList.h>
11f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Script/InputToken.h>
12f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/MC/InputBuilder.h>
13f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/MC/Attribute.h>
14f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Support/Path.h>
15f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Support/raw_ostream.h>
16f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Support/MsgHandling.h>
17f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/InputTree.h>
18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/LinkerScript.h>
19f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/LD/GroupReader.h>
20f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/Casting.h>
21f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <cassert>
22f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesusing namespace mcld;
24f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
25f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
26f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// GroupCmd
27f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
28f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesGroupCmd::GroupCmd(StringList& pStringList,
29f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                   InputTree& pInputTree,
30f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                   InputBuilder& pBuilder,
31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                   GroupReader& pGroupReader,
32f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                   const LinkerConfig& pConfig)
33f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  : ScriptCommand(ScriptCommand::GROUP),
34f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_StringList(pStringList),
35f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_InputTree(pInputTree),
36f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_Builder(pBuilder),
37f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_GroupReader(pGroupReader),
38f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_Config(pConfig)
39f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
40f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
41f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesGroupCmd::~GroupCmd()
43f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
44f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
45f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesvoid GroupCmd::dump() const
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
48f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  mcld::outs() << "GROUP ( ";
49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  bool prev = false, cur = false;
50f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (StringList::const_iterator it = m_StringList.begin(),
51f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    ie = m_StringList.end(); it != ie; ++it) {
52f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    assert((*it)->kind() == StrToken::Input);
53f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    InputToken* input = llvm::cast<InputToken>(*it);
54f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    cur = input->asNeeded();
55f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!prev && cur)
56f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      mcld::outs() << "AS_NEEDED ( ";
57f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else if (prev && !cur)
58f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      mcld::outs() << " )";
59f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (input->type() == InputToken::NameSpec)
61f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      mcld::outs() << "-l";
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    mcld::outs() << input->name() << " ";
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
64f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    prev = cur;
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (!m_StringList.empty() && prev)
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    mcld::outs() << " )";
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  mcld::outs() << " )\n";
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
73f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesvoid GroupCmd::activate(Module& pModule)
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
75f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  LinkerScript& script = pModule.getScript();
76f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // construct the Group tree
77f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_Builder.setCurrentTree(m_InputTree);
78f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // --start-group
79f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_Builder.enterGroup();
80f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  InputTree::iterator group = m_Builder.getCurrentNode();
81f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
82f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (StringList::const_iterator it = m_StringList.begin(),
83f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    ie = m_StringList.end(); it != ie; ++it) {
84f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
85f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    assert((*it)->kind() == StrToken::Input);
86f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    InputToken* token = llvm::cast<InputToken>(*it);
87f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (token->asNeeded())
88f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      m_Builder.getAttributes().setAsNeeded();
89f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else
90f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      m_Builder.getAttributes().unsetAsNeeded();
91f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
92f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    switch (token->type()) {
93f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    case InputToken::File: {
94f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      sys::fs::Path path;
95f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
96f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      // 1. Looking for file in the sysroot prefix, if a sysroot prefix is
97f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      // configured and the filename starts with '/'
98f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (script.hasSysroot() &&
99f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          (token->name().size() > 0 && token->name()[0] == '/')) {
100f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          path = script.sysroot();
101f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          path.append(token->name());
102f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      } else {
103f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // 2. Try to open the file in CWD
104f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        path.assign(token->name());
105f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (!sys::fs::exists(path)) {
106f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          // 3. Search through the library search path
107f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          sys::fs::Path* p =
108f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            script.directories().find(token->name(), Input::Script);
109f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          if (p != NULL)
110f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            path = *p;
111f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        }
112f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
113f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
114f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (!sys::fs::exists(path))
115f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        fatal(diag::err_cannot_open_input) << path.filename() << path;
116f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
117f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      m_Builder.createNode<InputTree::Positional>(
118f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        path.filename().native(), path, Input::Unknown);
119f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      break;
120f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
121f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    case InputToken::NameSpec: {
122f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      const sys::fs::Path* path = NULL;
123f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      // find out the real path of the namespec.
124f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (m_Builder.getConstraint().isSharedSystem()) {
125f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // In the system with shared object support, we can find both archive
126f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // and shared object.
127f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (m_Builder.getAttributes().isStatic()) {
128f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          // with --static, we must search an archive.
129f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          path = script.directories().find(token->name(), Input::Archive);
130f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        } else {
131f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          // otherwise, with --Bdynamic, we can find either an archive or a
132f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          // shared object.
133f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          path = script.directories().find(token->name(), Input::DynObj);
134f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        }
135f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      } else {
136f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // In the system without shared object support, only look for an archive
137f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        path = script.directories().find(token->name(), Input::Archive);
138f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
139f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
140f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (NULL == path)
141f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        fatal(diag::err_cannot_find_namespec) << token->name();
142f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
143f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      m_Builder.createNode<InputTree::Positional>(
144f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        token->name(), *path, Input::Unknown);
145f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      break;
146f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
147f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    default:
148f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      assert(0 && "Invalid script token in GROUP!");
149f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      break;
150f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    } // end of switch
151f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
152f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Input* input = *m_Builder.getCurrentNode();
153f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    assert(input != NULL);
154f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!m_Builder.setMemory(*input, FileHandle::ReadOnly))
155f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      error(diag::err_cannot_open_input) << input->name() << input->path();
156f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_Builder.setContext(*input);
157f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
158f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
159f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // --end-group
160f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_Builder.exitGroup();
161f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
162f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // read the group
163f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_GroupReader.readGroup(group, m_InputTree.end(), m_Builder, m_Config);
164f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
165f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
166