1//===- InputBuilder.cpp ---------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include "mcld/MC/InputBuilder.h" 10 11#include "mcld/LinkerConfig.h" 12#include "mcld/Config/Config.h" 13#include "mcld/MC/ContextFactory.h" 14#include "mcld/MC/InputFactory.h" 15#include "mcld/Support/MemoryAreaFactory.h" 16#include "mcld/Support/Path.h" 17 18namespace mcld { 19 20InputBuilder::InputBuilder(const LinkerConfig& pConfig) 21 : m_Config(pConfig), 22 m_pCurrentTree(NULL), 23 m_pMove(NULL), 24 m_Root(), 25 m_bOwnFactory(true) { 26 m_pInputFactory = new InputFactory(MCLD_NUM_OF_INPUTS, pConfig); 27 m_pContextFactory = new ContextFactory(MCLD_NUM_OF_INPUTS); 28 m_pMemFactory = new MemoryAreaFactory(MCLD_NUM_OF_INPUTS); 29} 30 31InputBuilder::InputBuilder(const LinkerConfig& pConfig, 32 InputFactory& pInputFactory, 33 ContextFactory& pContextFactory, 34 MemoryAreaFactory& pMemoryFactory, 35 bool pDelegate) 36 : m_Config(pConfig), 37 m_pInputFactory(&pInputFactory), 38 m_pMemFactory(&pMemoryFactory), 39 m_pContextFactory(&pContextFactory), 40 m_pCurrentTree(NULL), 41 m_pMove(NULL), 42 m_Root(), 43 m_bOwnFactory(pDelegate) { 44} 45 46InputBuilder::~InputBuilder() { 47 if (m_bOwnFactory) { 48 delete m_pInputFactory; 49 delete m_pContextFactory; 50 delete m_pMemFactory; 51 } 52} 53 54Input* InputBuilder::createInput(const std::string& pName, 55 const sys::fs::Path& pPath, 56 unsigned int pType, 57 off_t pFileOffset) { 58 return m_pInputFactory->produce(pName, pPath, pType, pFileOffset); 59} 60 61InputTree& InputBuilder::enterGroup() { 62 assert(m_pCurrentTree != NULL && m_pMove != NULL); 63 64 m_pCurrentTree->enterGroup(m_Root, *m_pMove); 65 m_pMove->move(m_Root); 66 m_ReturnStack.push(m_Root); 67 m_pMove = &InputTree::Downward; 68 69 return *m_pCurrentTree; 70} 71 72InputTree& InputBuilder::exitGroup() { 73 assert(m_pCurrentTree != NULL && m_pMove != NULL); 74 75 m_Root = m_ReturnStack.top(); 76 m_ReturnStack.pop(); 77 m_pMove = &InputTree::Afterward; 78 79 return *m_pCurrentTree; 80} 81 82bool InputBuilder::isInGroup() const { 83 return !m_ReturnStack.empty(); 84} 85 86const InputTree& InputBuilder::getCurrentTree() const { 87 assert(m_pCurrentTree != NULL && m_pMove != NULL); 88 return *m_pCurrentTree; 89} 90 91InputTree& InputBuilder::getCurrentTree() { 92 assert(m_pCurrentTree != NULL && m_pMove != NULL); 93 return *m_pCurrentTree; 94} 95 96void InputBuilder::setCurrentTree(InputTree& pInputTree) { 97 m_pCurrentTree = &pInputTree; 98 m_Root = m_pCurrentTree->root(); 99 m_pMove = &InputTree::Downward; 100} 101 102bool InputBuilder::setContext(Input& pInput, bool pCheck) { 103 // The object files in an archive have common path. Every object files in an 104 // archive needs a individual context. We identify the object files in an 105 // archive by its file offset. Their file offsets are not zero. 106 LDContext* context = NULL; 107 if (pInput.fileOffset() != 0 || !pCheck) { 108 // pInput is an object in an archive file. Produce a new context in this 109 // case. 110 context = m_pContextFactory->produce(); 111 } else { 112 // Using pInput.path() to avoid from creating context for identical file 113 // twice. 114 context = m_pContextFactory->produce(pInput.path()); 115 } 116 117 pInput.setContext(context); 118 return true; 119} 120 121bool InputBuilder::setMemory(Input& pInput, 122 FileHandle::OpenMode pMode, 123 FileHandle::Permission pPerm) { 124 MemoryArea* memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm); 125 pInput.setMemArea(memory); 126 return true; 127} 128 129bool InputBuilder::setMemory(Input& pInput, void* pMemBuffer, size_t pSize) { 130 MemoryArea* memory = m_pMemFactory->produce(pMemBuffer, pSize); 131 pInput.setMemArea(memory); 132 return true; 133} 134 135const AttrConstraint& InputBuilder::getConstraint() const { 136 return m_Config.attribute().constraint(); 137} 138 139const AttributeProxy& InputBuilder::getAttributes() const { 140 return m_pInputFactory->attr(); 141} 142 143AttributeProxy& InputBuilder::getAttributes() { 144 return m_pInputFactory->attr(); 145} 146 147} // namespace mcld 148