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