You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
8.0 KiB
247 lines
8.0 KiB
//===- ScriptFile.cpp -----------------------------------------------------===//
|
|
//
|
|
// The MCLinker Project
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "mcld/Script/ScriptFile.h"
|
|
|
|
#include "mcld/ADT/HashEntry.h"
|
|
#include "mcld/ADT/HashTable.h"
|
|
#include "mcld/ADT/StringHash.h"
|
|
#include "mcld/Script/AssertCmd.h"
|
|
#include "mcld/Script/EntryCmd.h"
|
|
#include "mcld/Script/GroupCmd.h"
|
|
#include "mcld/Script/InputCmd.h"
|
|
#include "mcld/Script/Operand.h"
|
|
#include "mcld/Script/OutputArchCmd.h"
|
|
#include "mcld/Script/OutputCmd.h"
|
|
#include "mcld/Script/OutputFormatCmd.h"
|
|
#include "mcld/Script/RpnExpr.h"
|
|
#include "mcld/Script/ScriptCommand.h"
|
|
#include "mcld/Script/SearchDirCmd.h"
|
|
#include "mcld/Script/SectionsCmd.h"
|
|
#include "mcld/Script/StringList.h"
|
|
#include "mcld/Script/StrToken.h"
|
|
#include "mcld/MC/Input.h"
|
|
#include "mcld/MC/InputBuilder.h"
|
|
#include "mcld/Support/MemoryArea.h"
|
|
#include "mcld/InputTree.h"
|
|
|
|
#include <llvm/Support/Casting.h>
|
|
#include <llvm/Support/ManagedStatic.h>
|
|
|
|
#include <cassert>
|
|
|
|
namespace mcld {
|
|
|
|
typedef HashEntry<std::string, void*, hash::StringCompare<std::string> >
|
|
ParserStrEntry;
|
|
typedef HashTable<ParserStrEntry,
|
|
hash::StringHash<hash::DJB>,
|
|
EntryFactory<ParserStrEntry> > ParserStrPool;
|
|
static llvm::ManagedStatic<ParserStrPool> g_ParserStrPool;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ScriptFile
|
|
//===----------------------------------------------------------------------===//
|
|
ScriptFile::ScriptFile(Kind pKind, Input& pInput, InputBuilder& pBuilder)
|
|
: m_Kind(pKind),
|
|
m_Input(pInput),
|
|
m_Name(pInput.path().native()),
|
|
m_pInputTree(NULL),
|
|
m_Builder(pBuilder),
|
|
m_bHasSectionsCmd(false),
|
|
m_bInSectionsCmd(false),
|
|
m_bInOutputSectDesc(false),
|
|
m_pRpnExpr(NULL),
|
|
m_pStringList(NULL),
|
|
m_bAsNeeded(false) {
|
|
// FIXME: move creation of input tree out of ScriptFile.
|
|
m_pInputTree = new InputTree();
|
|
}
|
|
|
|
ScriptFile::~ScriptFile() {
|
|
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
|
if (*it != NULL)
|
|
delete *it;
|
|
}
|
|
if (m_pInputTree != NULL)
|
|
delete m_pInputTree;
|
|
}
|
|
|
|
void ScriptFile::dump() const {
|
|
for (const_iterator it = begin(), ie = end(); it != ie; ++it)
|
|
(*it)->dump();
|
|
}
|
|
|
|
void ScriptFile::activate(Module& pModule) {
|
|
for (const_iterator it = begin(), ie = end(); it != ie; ++it)
|
|
(*it)->activate(pModule);
|
|
}
|
|
|
|
void ScriptFile::addEntryPoint(const std::string& pSymbol) {
|
|
EntryCmd* entry = new EntryCmd(pSymbol);
|
|
|
|
if (m_bInSectionsCmd) {
|
|
assert(!m_CommandQueue.empty());
|
|
SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
|
|
sections->push_back(entry);
|
|
} else {
|
|
m_CommandQueue.push_back(entry);
|
|
}
|
|
}
|
|
|
|
void ScriptFile::addOutputFormatCmd(const std::string& pName) {
|
|
m_CommandQueue.push_back(new OutputFormatCmd(pName));
|
|
}
|
|
|
|
void ScriptFile::addOutputFormatCmd(const std::string& pDefault,
|
|
const std::string& pBig,
|
|
const std::string& pLittle) {
|
|
m_CommandQueue.push_back(new OutputFormatCmd(pDefault, pBig, pLittle));
|
|
}
|
|
|
|
void ScriptFile::addInputCmd(StringList& pStringList,
|
|
ObjectReader& pObjectReader,
|
|
ArchiveReader& pArchiveReader,
|
|
DynObjReader& pDynObjReader,
|
|
const LinkerConfig& pConfig) {
|
|
m_CommandQueue.push_back(new InputCmd(pStringList,
|
|
*m_pInputTree,
|
|
m_Builder,
|
|
pObjectReader,
|
|
pArchiveReader,
|
|
pDynObjReader,
|
|
pConfig));
|
|
}
|
|
|
|
void ScriptFile::addGroupCmd(StringList& pStringList,
|
|
GroupReader& pGroupReader,
|
|
const LinkerConfig& pConfig) {
|
|
m_CommandQueue.push_back(new GroupCmd(
|
|
pStringList, *m_pInputTree, m_Builder, pGroupReader, pConfig));
|
|
}
|
|
|
|
void ScriptFile::addOutputCmd(const std::string& pFileName) {
|
|
m_CommandQueue.push_back(new OutputCmd(pFileName));
|
|
}
|
|
|
|
void ScriptFile::addSearchDirCmd(const std::string& pPath) {
|
|
m_CommandQueue.push_back(new SearchDirCmd(pPath));
|
|
}
|
|
|
|
void ScriptFile::addOutputArchCmd(const std::string& pArch) {
|
|
m_CommandQueue.push_back(new OutputArchCmd(pArch));
|
|
}
|
|
|
|
void ScriptFile::addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage) {
|
|
m_CommandQueue.push_back(new AssertCmd(pRpnExpr, pMessage));
|
|
}
|
|
|
|
void ScriptFile::addAssignment(const std::string& pSymbolName,
|
|
RpnExpr& pRpnExpr,
|
|
Assignment::Type pType) {
|
|
if (m_bInSectionsCmd) {
|
|
assert(!m_CommandQueue.empty());
|
|
SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
|
|
if (m_bInOutputSectDesc) {
|
|
assert(!sections->empty());
|
|
OutputSectDesc* output_desc =
|
|
llvm::cast<OutputSectDesc>(sections->back());
|
|
output_desc->push_back(new Assignment(Assignment::INPUT_SECTION,
|
|
pType,
|
|
*(SymOperand::create(pSymbolName)),
|
|
pRpnExpr));
|
|
} else {
|
|
sections->push_back(new Assignment(Assignment::OUTPUT_SECTION,
|
|
pType,
|
|
*(SymOperand::create(pSymbolName)),
|
|
pRpnExpr));
|
|
}
|
|
} else {
|
|
m_CommandQueue.push_back(new Assignment(Assignment::OUTSIDE_SECTIONS,
|
|
pType,
|
|
*(SymOperand::create(pSymbolName)),
|
|
pRpnExpr));
|
|
}
|
|
}
|
|
|
|
bool ScriptFile::hasSectionsCmd() const {
|
|
return m_bHasSectionsCmd;
|
|
}
|
|
|
|
void ScriptFile::enterSectionsCmd() {
|
|
m_bHasSectionsCmd = true;
|
|
m_bInSectionsCmd = true;
|
|
m_CommandQueue.push_back(new SectionsCmd());
|
|
}
|
|
|
|
void ScriptFile::leaveSectionsCmd() {
|
|
m_bInSectionsCmd = false;
|
|
}
|
|
|
|
void ScriptFile::enterOutputSectDesc(const std::string& pName,
|
|
const OutputSectDesc::Prolog& pProlog) {
|
|
assert(!m_CommandQueue.empty());
|
|
assert(m_bInSectionsCmd);
|
|
SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
|
|
sections->push_back(new OutputSectDesc(pName, pProlog));
|
|
|
|
m_bInOutputSectDesc = true;
|
|
}
|
|
|
|
void ScriptFile::leaveOutputSectDesc(const OutputSectDesc::Epilog& pEpilog) {
|
|
assert(!m_CommandQueue.empty());
|
|
assert(m_bInSectionsCmd);
|
|
SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
|
|
|
|
assert(!sections->empty() && m_bInOutputSectDesc);
|
|
OutputSectDesc* output_desc = llvm::cast<OutputSectDesc>(sections->back());
|
|
output_desc->setEpilog(pEpilog);
|
|
|
|
m_bInOutputSectDesc = false;
|
|
}
|
|
|
|
void ScriptFile::addInputSectDesc(InputSectDesc::KeepPolicy pPolicy,
|
|
const InputSectDesc::Spec& pSpec) {
|
|
assert(!m_CommandQueue.empty());
|
|
assert(m_bInSectionsCmd);
|
|
SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
|
|
|
|
assert(!sections->empty() && m_bInOutputSectDesc);
|
|
OutputSectDesc* output_sect = llvm::cast<OutputSectDesc>(sections->back());
|
|
|
|
output_sect->push_back(new InputSectDesc(pPolicy, pSpec, *output_sect));
|
|
}
|
|
|
|
RpnExpr* ScriptFile::createRpnExpr() {
|
|
m_pRpnExpr = RpnExpr::create();
|
|
return m_pRpnExpr;
|
|
}
|
|
|
|
StringList* ScriptFile::createStringList() {
|
|
m_pStringList = StringList::create();
|
|
return m_pStringList;
|
|
}
|
|
|
|
void ScriptFile::setAsNeeded(bool pEnable) {
|
|
m_bAsNeeded = pEnable;
|
|
}
|
|
|
|
const std::string& ScriptFile::createParserStr(const char* pText,
|
|
size_t pLength) {
|
|
bool exist = false;
|
|
ParserStrEntry* entry =
|
|
g_ParserStrPool->insert(std::string(pText, pLength), exist);
|
|
return entry->key();
|
|
}
|
|
|
|
void ScriptFile::clearParserStrPool() {
|
|
g_ParserStrPool->clear();
|
|
}
|
|
|
|
} // namespace mcld
|