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 18 namespace mcld { 19 20 InputBuilder::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 31 InputBuilder::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 46 InputBuilder::~InputBuilder() { 47 if (m_bOwnFactory) { 48 delete m_pInputFactory; 49 delete m_pContextFactory; 50 delete m_pMemFactory; 51 } 52 } 53 54 Input* 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 61 InputTree& 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 72 InputTree& 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 82 bool InputBuilder::isInGroup() const { 83 return !m_ReturnStack.empty(); 84 } 85 86 const InputTree& InputBuilder::getCurrentTree() const { 87 assert(m_pCurrentTree != NULL && m_pMove != NULL); 88 return *m_pCurrentTree; 89 } 90 91 InputTree& InputBuilder::getCurrentTree() { 92 assert(m_pCurrentTree != NULL && m_pMove != NULL); 93 return *m_pCurrentTree; 94 } 95 96 void InputBuilder::setCurrentTree(InputTree& pInputTree) { 97 m_pCurrentTree = &pInputTree; 98 m_Root = m_pCurrentTree->root(); 99 m_pMove = &InputTree::Downward; 100 } 101 102 bool 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 121 bool 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 129 bool 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 135 const AttrConstraint& InputBuilder::getConstraint() const { 136 return m_Config.attribute().constraint(); 137 } 138 139 const AttributeProxy& InputBuilder::getAttributes() const { 140 return m_pInputFactory->attr(); 141 } 142 143 AttributeProxy& InputBuilder::getAttributes() { 144 return m_pInputFactory->attr(); 145 } 146 147 } // namespace mcld 148