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
InputBuilder(const LinkerConfig & pConfig)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
InputBuilder(const LinkerConfig & pConfig,InputFactory & pInputFactory,ContextFactory & pContextFactory,MemoryAreaFactory & pMemoryFactory,bool pDelegate)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
~InputBuilder()44 InputBuilder::~InputBuilder()
45 {
46 if (m_bOwnFactory) {
47 delete m_pInputFactory;
48 delete m_pContextFactory;
49 delete m_pMemFactory;
50 }
51 }
52
createInput(const std::string & pName,const sys::fs::Path & pPath,unsigned int pType,off_t pFileOffset)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
enterGroup()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
exitGroup()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
isInGroup() const84 bool InputBuilder::isInGroup() const
85 {
86 return !m_ReturnStack.empty();
87 }
88
getCurrentTree() const89 const InputTree& InputBuilder::getCurrentTree() const
90 {
91 assert(NULL != m_pCurrentTree && NULL != m_pMove);
92 return *m_pCurrentTree;
93 }
94
getCurrentTree()95 InputTree& InputBuilder::getCurrentTree()
96 {
97 assert(NULL != m_pCurrentTree && NULL != m_pMove);
98 return *m_pCurrentTree;
99 }
100
setCurrentTree(InputTree & pInputTree)101 void InputBuilder::setCurrentTree(InputTree& pInputTree)
102 {
103 m_pCurrentTree = &pInputTree;
104 m_Root = m_pCurrentTree->root();
105 m_pMove = &InputTree::Downward;
106 }
107
setContext(Input & pInput,bool pCheck)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
setMemory(Input & pInput,FileHandle::OpenMode pMode,FileHandle::Permission pPerm)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
setMemory(Input & pInput,void * pMemBuffer,size_t pSize)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
getConstraint() const149 const AttrConstraint& InputBuilder::getConstraint() const
150 {
151 return m_Config.attribute().constraint();
152 }
153
getAttributes() const154 const AttributeProxy& InputBuilder::getAttributes() const
155 {
156 return m_pInputFactory->attr();
157 }
158
getAttributes()159 AttributeProxy& InputBuilder::getAttributes()
160 {
161 return m_pInputFactory->attr();
162 }
163
164