137b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===- InputCmd.cpp -------------------------------------------------------===//
237b74a387bb3993387029859c2d9d051c41c724eStephen Hines//
337b74a387bb3993387029859c2d9d051c41c724eStephen Hines//                     The MCLinker Project
437b74a387bb3993387029859c2d9d051c41c724eStephen Hines//
537b74a387bb3993387029859c2d9d051c41c724eStephen Hines// This file is distributed under the University of Illinois Open Source
637b74a387bb3993387029859c2d9d051c41c724eStephen Hines// License. See LICENSE.TXT for details.
737b74a387bb3993387029859c2d9d051c41c724eStephen Hines//
837b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/InputCmd.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/Archive.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ArchiveReader.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/DynObjReader.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ObjectReader.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Attribute.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/InputBuilder.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/InputToken.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Script/StringList.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/Path.h"
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/raw_ostream.h"
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/InputTree.h"
2337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerScript.h"
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Module.h"
2637b74a387bb3993387029859c2d9d051c41c724eStephen Hines
2737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <llvm/Support/Casting.h>
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <cassert>
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <iostream>
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===//
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines// InputCmd
3637b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===//
3737b74a387bb3993387029859c2d9d051c41c724eStephen HinesInputCmd::InputCmd(StringList& pStringList,
3837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   InputTree& pInputTree,
3937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   InputBuilder& pBuilder,
4037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   ObjectReader& pObjectReader,
4137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   ArchiveReader& pArchiveReader,
4237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   DynObjReader& pDynObjReader,
4337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   const LinkerConfig& pConfig)
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : ScriptCommand(ScriptCommand::INPUT),
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_StringList(pStringList),
4637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_InputTree(pInputTree),
4737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Builder(pBuilder),
4837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_ObjectReader(pObjectReader),
4937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_ArchiveReader(pArchiveReader),
5037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_DynObjReader(pDynObjReader),
5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Config(pConfig) {
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
5437b74a387bb3993387029859c2d9d051c41c724eStephen HinesInputCmd::~InputCmd() {
5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
5637b74a387bb3993387029859c2d9d051c41c724eStephen Hines
5737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid InputCmd::dump() const {
5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  mcld::outs() << "INPUT ( ";
5937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool prev = false, cur = false;
6037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (StringList::const_iterator it = m_StringList.begin(),
6137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  ie = m_StringList.end();
6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
6337b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it) {
6437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    assert((*it)->kind() == StrToken::Input);
6537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    InputToken* input = llvm::cast<InputToken>(*it);
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    cur = input->asNeeded();
6737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (!prev && cur)
6837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      mcld::outs() << "AS_NEEDED ( ";
6937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    else if (prev && !cur)
7037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      mcld::outs() << " )";
7137b74a387bb3993387029859c2d9d051c41c724eStephen Hines
7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (input->type() == InputToken::NameSpec)
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      mcld::outs() << "-l";
7437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    mcld::outs() << input->name() << " ";
7537b74a387bb3993387029859c2d9d051c41c724eStephen Hines
7637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    prev = cur;
7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
7937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (!m_StringList.empty() && prev)
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    mcld::outs() << " )";
8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines
8237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  mcld::outs() << " )\n";
8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines
8537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid InputCmd::activate(Module& pModule) {
8637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  LinkerScript& script = pModule.getScript();
8737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // construct the INPUT tree
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  m_Builder.setCurrentTree(m_InputTree);
8937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
9037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool is_begin_marked = false;
9137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  InputTree::iterator input_begin;
9237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (StringList::const_iterator it = m_StringList.begin(),
9437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  ie = m_StringList.end();
9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it) {
9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    assert((*it)->kind() == StrToken::Input);
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    InputToken* token = llvm::cast<InputToken>(*it);
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (token->asNeeded())
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Builder.getAttributes().setAsNeeded();
10137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    else
10237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Builder.getAttributes().unsetAsNeeded();
10337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    switch (token->type()) {
10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      case InputToken::File: {
10637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        sys::fs::Path path;
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines
10837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // 1. Looking for file in the sysroot prefix, if a sysroot prefix is
10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // configured and the filename starts with '/'
11037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (script.hasSysroot() &&
11137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            (token->name().size() > 0 && token->name()[0] == '/')) {
11237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          path = script.sysroot();
11337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          path.append(token->name());
11437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        } else {
11537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // 2. Try to open the file in CWD
11637b74a387bb3993387029859c2d9d051c41c724eStephen Hines          path.assign(token->name());
11737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          if (!sys::fs::exists(path)) {
11837b74a387bb3993387029859c2d9d051c41c724eStephen Hines            // 3. Search through the library search path
11937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            sys::fs::Path* p =
12037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                script.directories().find(token->name(), Input::Script);
12137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            if (p != NULL)
12237b74a387bb3993387029859c2d9d051c41c724eStephen Hines              path = *p;
12337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          }
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        }
12537b74a387bb3993387029859c2d9d051c41c724eStephen Hines
12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!sys::fs::exists(path))
12737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          fatal(diag::err_cannot_open_input) << path.filename() << path;
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Builder.createNode<InputTree::Positional>(
13037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            path.filename().native(), path, Input::Unknown);
13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        break;
13237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }
13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      case InputToken::NameSpec: {
13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        const sys::fs::Path* path = NULL;
13537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // find out the real path of the namespec.
13637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (m_Builder.getConstraint().isSharedSystem()) {
13737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // In the system with shared object support, we can find both archive
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // and shared object.
13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines          if (m_Builder.getAttributes().isStatic()) {
14037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            // with --static, we must search an archive.
14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            path = script.directories().find(token->name(), Input::Archive);
14237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          } else {
14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines            // otherwise, with --Bdynamic, we can find either an archive or a
14437b74a387bb3993387029859c2d9d051c41c724eStephen Hines            // shared object.
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines            path = script.directories().find(token->name(), Input::DynObj);
14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines          }
14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        } else {
14837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // In the system without shared object support, only look for an
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines          // archive
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines          path = script.directories().find(token->name(), Input::Archive);
15137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        }
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (path == NULL)
15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          fatal(diag::err_cannot_find_namespec) << token->name();
15537b74a387bb3993387029859c2d9d051c41c724eStephen Hines
15637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_Builder.createNode<InputTree::Positional>(
15737b74a387bb3993387029859c2d9d051c41c724eStephen Hines            token->name(), *path, Input::Unknown);
15837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        break;
15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }
16037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      default:
16137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        assert(0 && "Invalid script token in INPUT!");
16237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        break;
16337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }  // end of switch
16437b74a387bb3993387029859c2d9d051c41c724eStephen Hines
16537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    InputTree::iterator input = m_Builder.getCurrentNode();
16637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (!is_begin_marked) {
16737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      input_begin = input;
16837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      is_begin_marked = true;
16937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }
17037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    assert(*input != NULL);
17137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (!m_Builder.setMemory(**input,
17237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             FileHandle::OpenMode(FileHandle::ReadOnly),
17337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             FileHandle::Permission(FileHandle::System))) {
17437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      error(diag::err_cannot_open_input) << (*input)->name()
17537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                         << (*input)->path();
17637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }
17737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_Builder.setContext(**input);
17837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }
17937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
18037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (InputTree::iterator input = input_begin, ie = m_InputTree.end();
18137b74a387bb3993387029859c2d9d051c41c724eStephen Hines       input != ie;
18237b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++input) {
18337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    bool doContinue = false;
18437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (m_ObjectReader.isMyFormat(**input, doContinue)) {
18537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (*input)->setType(Input::Object);
18637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_ObjectReader.readHeader(**input);
18737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_ObjectReader.readSections(**input);
18837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_ObjectReader.readSymbols(**input);
18937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pModule.getObjectList().push_back(*input);
19037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else if (doContinue && m_DynObjReader.isMyFormat(**input, doContinue)) {
19137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (*input)->setType(Input::DynObj);
19237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_DynObjReader.readHeader(**input);
19337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_DynObjReader.readSymbols(**input);
19437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pModule.getLibraryList().push_back(*input);
19537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else if (doContinue && m_ArchiveReader.isMyFormat(**input, doContinue)) {
19637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (*input)->setType(Input::Archive);
19737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (m_Config.options().isInExcludeLIBS(**input)) {
19837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        (*input)->setNoExport();
19937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }
20037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      Archive archive(**input, m_Builder);
20137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_ArchiveReader.readArchive(m_Config, archive);
20237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (archive.numOfObjectMember() > 0) {
20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_InputTree.merge<InputTree::Inclusive>(input, archive.inputs());
20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }
20537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
20637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (m_Config.options().warnMismatch())
20737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        warning(diag::warn_unrecognized_input_file)
20837b74a387bb3993387029859c2d9d051c41c724eStephen Hines            << (*input)->path() << m_Config.targets().triple().str();
20937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }
21037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }
21137b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
21237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
21337b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
214