InputBuilder.cpp revision f33f6de54db174aa679a4b6d1e040d37e95541c0
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
18using namespace mcld;
19
20InputBuilder::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
30InputBuilder::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
44InputBuilder::~InputBuilder()
45{
46  if (m_bOwnFactory) {
47    delete m_pInputFactory;
48    delete m_pContextFactory;
49    delete m_pMemFactory;
50  }
51}
52
53Input* 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
61InputTree& 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
73InputTree& 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
84bool InputBuilder::isInGroup() const
85{
86  return !m_ReturnStack.empty();
87}
88
89const InputTree& InputBuilder::getCurrentTree() const
90{
91  assert(NULL != m_pCurrentTree && NULL != m_pMove);
92  return *m_pCurrentTree;
93}
94
95InputTree& InputBuilder::getCurrentTree()
96{
97  assert(NULL != m_pCurrentTree && NULL != m_pMove);
98  return *m_pCurrentTree;
99}
100
101void InputBuilder::setCurrentTree(InputTree& pInputTree)
102{
103  m_pCurrentTree = &pInputTree;
104  m_Root = m_pCurrentTree->root();
105  m_pMove = &InputTree::Downward;
106}
107
108bool 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
129bool InputBuilder::setMemory(Input& pInput,
130                             FileHandle::OpenMode pMode,
131                             FileHandle::Permission pPerm)
132{
133  MemoryArea *memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm);
134  pInput.setMemArea(memory);
135  return true;
136}
137
138bool InputBuilder::setMemory(Input& pInput, void* pMemBuffer, size_t pSize)
139{
140  MemoryArea *memory = m_pMemFactory->produce(pMemBuffer, pSize);
141  pInput.setMemArea(memory);
142  return true;
143}
144
145const AttrConstraint& InputBuilder::getConstraint() const
146{
147  return m_Config.attribute().constraint();
148}
149
150const AttributeProxy& InputBuilder::getAttributes() const
151{
152  return m_pInputFactory->attr();
153}
154
155AttributeProxy& InputBuilder::getAttributes()
156{
157  return m_pInputFactory->attr();
158}
159
160