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/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 
     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 
     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 
     44 InputBuilder::~InputBuilder()
     45 {
     46   if (m_bOwnFactory) {
     47     delete m_pInputFactory;
     48     delete m_pContextFactory;
     49     delete m_pMemFactory;
     50   }
     51 }
     52 
     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 
     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 
     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 
     84 bool InputBuilder::isInGroup() const
     85 {
     86   return !m_ReturnStack.empty();
     87 }
     88 
     89 const InputTree& InputBuilder::getCurrentTree() const
     90 {
     91   assert(NULL != m_pCurrentTree && NULL != m_pMove);
     92   return *m_pCurrentTree;
     93 }
     94 
     95 InputTree& InputBuilder::getCurrentTree()
     96 {
     97   assert(NULL != m_pCurrentTree && NULL != m_pMove);
     98   return *m_pCurrentTree;
     99 }
    100 
    101 void InputBuilder::setCurrentTree(InputTree& pInputTree)
    102 {
    103   m_pCurrentTree = &pInputTree;
    104   m_Root = m_pCurrentTree->root();
    105   m_pMove = &InputTree::Downward;
    106 }
    107 
    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 
    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 
    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 
    149 const AttrConstraint& InputBuilder::getConstraint() const
    150 {
    151   return m_Config.attribute().constraint();
    152 }
    153 
    154 const AttributeProxy& InputBuilder::getAttributes() const
    155 {
    156   return m_pInputFactory->attr();
    157 }
    158 
    159 AttributeProxy& InputBuilder::getAttributes()
    160 {
    161   return m_pInputFactory->attr();
    162 }
    163 
    164