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 
InputBuilder(const LinkerConfig & pConfig)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 
InputBuilder(const LinkerConfig & pConfig,InputFactory & pInputFactory,ContextFactory & pContextFactory,MemoryAreaFactory & pMemoryFactory,bool pDelegate)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 
~InputBuilder()46 InputBuilder::~InputBuilder() {
47   if (m_bOwnFactory) {
48     delete m_pInputFactory;
49     delete m_pContextFactory;
50     delete m_pMemFactory;
51   }
52 }
53 
createInput(const std::string & pName,const sys::fs::Path & pPath,unsigned int pType,off_t pFileOffset)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 
enterGroup()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 
exitGroup()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 
isInGroup() const82 bool InputBuilder::isInGroup() const {
83   return !m_ReturnStack.empty();
84 }
85 
getCurrentTree() const86 const InputTree& InputBuilder::getCurrentTree() const {
87   assert(m_pCurrentTree != NULL && m_pMove != NULL);
88   return *m_pCurrentTree;
89 }
90 
getCurrentTree()91 InputTree& InputBuilder::getCurrentTree() {
92   assert(m_pCurrentTree != NULL && m_pMove != NULL);
93   return *m_pCurrentTree;
94 }
95 
setCurrentTree(InputTree & pInputTree)96 void InputBuilder::setCurrentTree(InputTree& pInputTree) {
97   m_pCurrentTree = &pInputTree;
98   m_Root = m_pCurrentTree->root();
99   m_pMove = &InputTree::Downward;
100 }
101 
setContext(Input & pInput,bool pCheck)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 
setMemory(Input & pInput,FileHandle::OpenMode pMode,FileHandle::Permission pPerm)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 
setMemory(Input & pInput,void * pMemBuffer,size_t pSize)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 
getConstraint() const135 const AttrConstraint& InputBuilder::getConstraint() const {
136   return m_Config.attribute().constraint();
137 }
138 
getAttributes() const139 const AttributeProxy& InputBuilder::getAttributes() const {
140   return m_pInputFactory->attr();
141 }
142 
getAttributes()143 AttributeProxy& InputBuilder::getAttributes() {
144   return m_pInputFactory->attr();
145 }
146 
147 }  // namespace mcld
148