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//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/GroupCmd.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/GroupReader.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/InputBuilder.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Attribute.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/InputToken.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/StringList.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/Path.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/raw_ostream.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/InputTree.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerScript.h"
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines
22f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/Casting.h>
23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <cassert>
24f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
26f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
27f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
28f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// GroupCmd
29f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
30f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesGroupCmd::GroupCmd(StringList& pStringList,
31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                   InputTree& pInputTree,
32f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                   InputBuilder& pBuilder,
33f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                   GroupReader& pGroupReader,
34f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                   const LinkerConfig& pConfig)
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : ScriptCommand(ScriptCommand::GROUP),
3637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_StringList(pStringList),
3737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_InputTree(pInputTree),
3837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Builder(pBuilder),
3937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_GroupReader(pGroupReader),
4037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Config(pConfig) {
41f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
4337b74a387bb3993387029859c2d9d051c41c724eStephen HinesGroupCmd::~GroupCmd() {
44f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
45f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
4637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid GroupCmd::dump() const {
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  mcld::outs() << "GROUP ( ";
48f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  bool prev = false, cur = false;
49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (StringList::const_iterator it = m_StringList.begin(),
5037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  ie = m_StringList.end();
5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it) {
53f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    assert((*it)->kind() == StrToken::Input);
54f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    InputToken* input = llvm::cast<InputToken>(*it);
55f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    cur = input->asNeeded();
56f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!prev && cur)
57f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      mcld::outs() << "AS_NEEDED ( ";
58f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else if (prev && !cur)
59f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      mcld::outs() << " )";
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
61f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (input->type() == InputToken::NameSpec)
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      mcld::outs() << "-l";
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    mcld::outs() << input->name() << " ";
64f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    prev = cur;
66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (!m_StringList.empty() && prev)
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    mcld::outs() << " )";
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  mcld::outs() << " )\n";
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
73f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
7437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid GroupCmd::activate(Module& pModule) {
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(),
8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  ie = m_StringList.end();
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
8537b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it) {
86f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    assert((*it)->kind() == StrToken::Input);
87f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    InputToken* token = llvm::cast<InputToken>(*it);
88f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (token->asNeeded())
89f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      m_Builder.getAttributes().setAsNeeded();
90f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else
91f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      m_Builder.getAttributes().unsetAsNeeded();
92f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
93f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    switch (token->type()) {
9437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      case InputToken::File: {
9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        sys::fs::Path path;
96f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // 1. Looking for file in the sysroot prefix, if a sysroot prefix is
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // configured and the filename starts with '/'
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (script.hasSysroot() &&
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            (token->name().size() > 0 && token->name()[0] == '/')) {
101f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          path = script.sysroot();
102f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          path.append(token->name());
10337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        } else {
10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // 2. Try to open the file in CWD
10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          path.assign(token->name());
10637b74a387bb3993387029859c2d9d051c41c724eStephen Hines          if (!sys::fs::exists(path)) {
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines            // 3. Search through the library search path
10837b74a387bb3993387029859c2d9d051c41c724eStephen Hines            sys::fs::Path* p =
10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                script.directories().find(token->name(), Input::Script);
11037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            if (p != NULL)
11137b74a387bb3993387029859c2d9d051c41c724eStephen Hines              path = *p;
11237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          }
113f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        }
114f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
11537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!sys::fs::exists(path))
11637b74a387bb3993387029859c2d9d051c41c724eStephen Hines          fatal(diag::err_cannot_open_input) << path.filename() << path;
117f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
11837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Builder.createNode<InputTree::Positional>(
11937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            path.filename().native(), path, Input::Unknown);
12037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        break;
12137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }
12237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      case InputToken::NameSpec: {
12337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        const sys::fs::Path* path = NULL;
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // find out the real path of the namespec.
12537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (m_Builder.getConstraint().isSharedSystem()) {
12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // In the system with shared object support, we can find both archive
12737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // and shared object.
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          if (m_Builder.getAttributes().isStatic()) {
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            // with --static, we must search an archive.
13037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            path = script.directories().find(token->name(), Input::Archive);
13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          } else {
13237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            // otherwise, with --Bdynamic, we can find either an archive or a
13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines            // shared object.
13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines            path = script.directories().find(token->name(), Input::DynObj);
13537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          }
136f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        } else {
13737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // In the system without shared object support, only look for an
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // archive
13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines          path = script.directories().find(token->name(), Input::Archive);
140f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        }
141f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
14237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (path == NULL)
14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          fatal(diag::err_cannot_find_namespec) << token->name();
144f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Builder.createNode<InputTree::Positional>(
14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines            token->name(), *path, Input::Unknown);
14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        break;
14837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      default:
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        assert(0 && "Invalid script token in GROUP!");
15137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        break;
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }  // end of switch
153f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
154f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Input* input = *m_Builder.getCurrentNode();
155f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    assert(input != NULL);
15637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (!m_Builder.setMemory(*input, FileHandle::OpenMode(FileHandle::ReadOnly),
15737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             FileHandle::Permission(FileHandle::System))) {
158f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      error(diag::err_cannot_open_input) << input->name() << input->path();
15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }
160f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    m_Builder.setContext(*input);
161f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
162f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
163f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // --end-group
164f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_Builder.exitGroup();
165f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
166f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // read the group
167f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_GroupReader.readGroup(group, m_InputTree.end(), m_Builder, m_Config);
168f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
169f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
17037b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
171