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