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.
148 lines
4.3 KiB
148 lines
4.3 KiB
4 months ago
|
//===- InputBuilder.cpp ---------------------------------------------------===//
|
||
|
//
|
||
|
// The MCLinker Project
|
||
|
//
|
||
|
// This file is distributed under the University of Illinois Open Source
|
||
|
// License. See LICENSE.TXT for details.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
#include "mcld/MC/InputBuilder.h"
|
||
|
|
||
|
#include "mcld/LinkerConfig.h"
|
||
|
#include "mcld/Config/Config.h"
|
||
|
#include "mcld/MC/ContextFactory.h"
|
||
|
#include "mcld/MC/InputFactory.h"
|
||
|
#include "mcld/Support/MemoryAreaFactory.h"
|
||
|
#include "mcld/Support/Path.h"
|
||
|
|
||
|
namespace mcld {
|
||
|
|
||
|
InputBuilder::InputBuilder(const LinkerConfig& pConfig)
|
||
|
: m_Config(pConfig),
|
||
|
m_pCurrentTree(NULL),
|
||
|
m_pMove(NULL),
|
||
|
m_Root(),
|
||
|
m_bOwnFactory(true) {
|
||
|
m_pInputFactory = new InputFactory(MCLD_NUM_OF_INPUTS, pConfig);
|
||
|
m_pContextFactory = new ContextFactory(MCLD_NUM_OF_INPUTS);
|
||
|
m_pMemFactory = new MemoryAreaFactory(MCLD_NUM_OF_INPUTS);
|
||
|
}
|
||
|
|
||
|
InputBuilder::InputBuilder(const LinkerConfig& pConfig,
|
||
|
InputFactory& pInputFactory,
|
||
|
ContextFactory& pContextFactory,
|
||
|
MemoryAreaFactory& pMemoryFactory,
|
||
|
bool pDelegate)
|
||
|
: m_Config(pConfig),
|
||
|
m_pInputFactory(&pInputFactory),
|
||
|
m_pMemFactory(&pMemoryFactory),
|
||
|
m_pContextFactory(&pContextFactory),
|
||
|
m_pCurrentTree(NULL),
|
||
|
m_pMove(NULL),
|
||
|
m_Root(),
|
||
|
m_bOwnFactory(pDelegate) {
|
||
|
}
|
||
|
|
||
|
InputBuilder::~InputBuilder() {
|
||
|
if (m_bOwnFactory) {
|
||
|
delete m_pInputFactory;
|
||
|
delete m_pContextFactory;
|
||
|
delete m_pMemFactory;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Input* InputBuilder::createInput(const std::string& pName,
|
||
|
const sys::fs::Path& pPath,
|
||
|
unsigned int pType,
|
||
|
off_t pFileOffset) {
|
||
|
return m_pInputFactory->produce(pName, pPath, pType, pFileOffset);
|
||
|
}
|
||
|
|
||
|
InputTree& InputBuilder::enterGroup() {
|
||
|
assert(m_pCurrentTree != NULL && m_pMove != NULL);
|
||
|
|
||
|
m_pCurrentTree->enterGroup(m_Root, *m_pMove);
|
||
|
m_pMove->move(m_Root);
|
||
|
m_ReturnStack.push(m_Root);
|
||
|
m_pMove = &InputTree::Downward;
|
||
|
|
||
|
return *m_pCurrentTree;
|
||
|
}
|
||
|
|
||
|
InputTree& InputBuilder::exitGroup() {
|
||
|
assert(m_pCurrentTree != NULL && m_pMove != NULL);
|
||
|
|
||
|
m_Root = m_ReturnStack.top();
|
||
|
m_ReturnStack.pop();
|
||
|
m_pMove = &InputTree::Afterward;
|
||
|
|
||
|
return *m_pCurrentTree;
|
||
|
}
|
||
|
|
||
|
bool InputBuilder::isInGroup() const {
|
||
|
return !m_ReturnStack.empty();
|
||
|
}
|
||
|
|
||
|
const InputTree& InputBuilder::getCurrentTree() const {
|
||
|
assert(m_pCurrentTree != NULL && m_pMove != NULL);
|
||
|
return *m_pCurrentTree;
|
||
|
}
|
||
|
|
||
|
InputTree& InputBuilder::getCurrentTree() {
|
||
|
assert(m_pCurrentTree != NULL && m_pMove != NULL);
|
||
|
return *m_pCurrentTree;
|
||
|
}
|
||
|
|
||
|
void InputBuilder::setCurrentTree(InputTree& pInputTree) {
|
||
|
m_pCurrentTree = &pInputTree;
|
||
|
m_Root = m_pCurrentTree->root();
|
||
|
m_pMove = &InputTree::Downward;
|
||
|
}
|
||
|
|
||
|
bool InputBuilder::setContext(Input& pInput, bool pCheck) {
|
||
|
// The object files in an archive have common path. Every object files in an
|
||
|
// archive needs a individual context. We identify the object files in an
|
||
|
// archive by its file offset. Their file offsets are not zero.
|
||
|
LDContext* context = NULL;
|
||
|
if (pInput.fileOffset() != 0 || !pCheck) {
|
||
|
// pInput is an object in an archive file. Produce a new context in this
|
||
|
// case.
|
||
|
context = m_pContextFactory->produce();
|
||
|
} else {
|
||
|
// Using pInput.path() to avoid from creating context for identical file
|
||
|
// twice.
|
||
|
context = m_pContextFactory->produce(pInput.path());
|
||
|
}
|
||
|
|
||
|
pInput.setContext(context);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool InputBuilder::setMemory(Input& pInput,
|
||
|
FileHandle::OpenMode pMode,
|
||
|
FileHandle::Permission pPerm) {
|
||
|
MemoryArea* memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm);
|
||
|
pInput.setMemArea(memory);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool InputBuilder::setMemory(Input& pInput, void* pMemBuffer, size_t pSize) {
|
||
|
MemoryArea* memory = m_pMemFactory->produce(pMemBuffer, pSize);
|
||
|
pInput.setMemArea(memory);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
const AttrConstraint& InputBuilder::getConstraint() const {
|
||
|
return m_Config.attribute().constraint();
|
||
|
}
|
||
|
|
||
|
const AttributeProxy& InputBuilder::getAttributes() const {
|
||
|
return m_pInputFactory->attr();
|
||
|
}
|
||
|
|
||
|
AttributeProxy& InputBuilder::getAttributes() {
|
||
|
return m_pInputFactory->attr();
|
||
|
}
|
||
|
|
||
|
} // namespace mcld
|