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