Home | History | Annotate | Download | only in MC
      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 
     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 
     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 
     46 InputBuilder::~InputBuilder() {
     47   if (m_bOwnFactory) {
     48     delete m_pInputFactory;
     49     delete m_pContextFactory;
     50     delete m_pMemFactory;
     51   }
     52 }
     53 
     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 
     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 
     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 
     82 bool InputBuilder::isInGroup() const {
     83   return !m_ReturnStack.empty();
     84 }
     85 
     86 const InputTree& InputBuilder::getCurrentTree() const {
     87   assert(m_pCurrentTree != NULL && m_pMove != NULL);
     88   return *m_pCurrentTree;
     89 }
     90 
     91 InputTree& InputBuilder::getCurrentTree() {
     92   assert(m_pCurrentTree != NULL && m_pMove != NULL);
     93   return *m_pCurrentTree;
     94 }
     95 
     96 void InputBuilder::setCurrentTree(InputTree& pInputTree) {
     97   m_pCurrentTree = &pInputTree;
     98   m_Root = m_pCurrentTree->root();
     99   m_pMove = &InputTree::Downward;
    100 }
    101 
    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 
    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 
    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 
    135 const AttrConstraint& InputBuilder::getConstraint() const {
    136   return m_Config.attribute().constraint();
    137 }
    138 
    139 const AttributeProxy& InputBuilder::getAttributes() const {
    140   return m_pInputFactory->attr();
    141 }
    142 
    143 AttributeProxy& InputBuilder::getAttributes() {
    144   return m_pInputFactory->attr();
    145 }
    146 
    147 }  // namespace mcld
    148