• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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