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