Home | History | Annotate | Download | only in Object
      1 //===- ObjectBuilder.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/Object/ObjectBuilder.h>
     10 
     11 #include <mcld/Module.h>
     12 #include <mcld/LinkerScript.h>
     13 #include <mcld/IRBuilder.h>
     14 #include <mcld/Object/SectionMap.h>
     15 #include <mcld/LD/LDSection.h>
     16 #include <mcld/LD/SectionData.h>
     17 #include <mcld/LD/EhFrame.h>
     18 #include <mcld/Fragment/AlignFragment.h>
     19 #include <mcld/Fragment/NullFragment.h>
     20 #include <mcld/Fragment/FillFragment.h>
     21 
     22 #include <llvm/Support/Casting.h>
     23 
     24 using namespace mcld;
     25 
     26 //===----------------------------------------------------------------------===//
     27 // ObjectBuilder
     28 //===----------------------------------------------------------------------===//
     29 ObjectBuilder::ObjectBuilder(Module& pTheModule)
     30   : m_Module(pTheModule) {
     31 }
     32 
     33 /// CreateSection - create an output section.
     34 LDSection* ObjectBuilder::CreateSection(const std::string& pName,
     35                                         LDFileFormat::Kind pKind,
     36                                         uint32_t pType,
     37                                         uint32_t pFlag,
     38                                         uint32_t pAlign)
     39 {
     40   // try to get one from output LDSection
     41   SectionMap::const_mapping pair =
     42     m_Module.getScript().sectionMap().find("*", pName);
     43 
     44   std::string output_name = (pair.first == NULL) ? pName : pair.first->name();
     45 
     46   LDSection* output_sect = m_Module.getSection(output_name);
     47   if (NULL == output_sect) {
     48     output_sect = LDSection::Create(pName, pKind, pType, pFlag);
     49     output_sect->setAlign(pAlign);
     50     m_Module.getSectionTable().push_back(output_sect);
     51   }
     52   return output_sect;
     53 }
     54 
     55 /// MergeSection - merge the pInput section to the pOutput section
     56 LDSection* ObjectBuilder::MergeSection(const Input& pInputFile,
     57                                        LDSection& pInputSection)
     58 {
     59   SectionMap::mapping pair =
     60     m_Module.getScript().sectionMap().find(pInputFile.path().native(),
     61                                            pInputSection.name());
     62 
     63   if (pair.first != NULL && pair.first->isDiscard()) {
     64     pInputSection.setKind(LDFileFormat::Ignore);
     65     return NULL;
     66   }
     67 
     68   std::string output_name = (pair.first == NULL) ?
     69                             pInputSection.name() : pair.first->name();
     70   LDSection* target = m_Module.getSection(output_name);
     71 
     72   if (NULL == target) {
     73     target = LDSection::Create(output_name,
     74                                pInputSection.kind(),
     75                                pInputSection.type(),
     76                                pInputSection.flag());
     77     target->setAlign(pInputSection.align());
     78     m_Module.getSectionTable().push_back(target);
     79   }
     80 
     81   switch (target->kind()) {
     82     case LDFileFormat::EhFrame: {
     83       EhFrame* eh_frame = NULL;
     84       if (target->hasEhFrame())
     85         eh_frame = target->getEhFrame();
     86       else
     87         eh_frame = IRBuilder::CreateEhFrame(*target);
     88 
     89       eh_frame->merge(pInputFile, *pInputSection.getEhFrame());
     90       UpdateSectionAlign(*target, pInputSection);
     91       return target;
     92     }
     93     default: {
     94       if (!target->hasSectionData())
     95         IRBuilder::CreateSectionData(*target);
     96 
     97       SectionData* data = NULL;
     98       if (pair.first != NULL) {
     99         assert(pair.second != NULL);
    100         data = pair.second->getSection()->getSectionData();
    101       } else {
    102         // orphan section
    103         data = target->getSectionData();
    104       }
    105 
    106       if (MoveSectionData(*pInputSection.getSectionData(), *data)) {
    107         UpdateSectionAlign(*target, pInputSection);
    108         return target;
    109       }
    110       return NULL;
    111     }
    112   }
    113   return target;
    114 }
    115 
    116 /// MoveSectionData - move the fragments of pTO section data to pTo
    117 bool ObjectBuilder::MoveSectionData(SectionData& pFrom, SectionData& pTo)
    118 {
    119   assert(&pFrom != &pTo && "Cannot move section data to itself!");
    120 
    121   uint64_t offset = pTo.getSection().size();
    122   AlignFragment* align = NULL;
    123   if (pFrom.getSection().align() > 1) {
    124     // if the align constraint is larger than 1, append an alignment
    125     align = new AlignFragment(pFrom.getSection().align(), // alignment
    126                               0x0, // the filled value
    127                               1u,  // the size of filled value
    128                               pFrom.getSection().align() - 1 // max bytes to emit
    129                               );
    130     align->setOffset(offset);
    131     align->setParent(&pTo);
    132     pTo.getFragmentList().push_back(align);
    133     offset += align->size();
    134   }
    135 
    136   // move fragments from pFrom to pTO
    137   SectionData::FragmentListType& from_list = pFrom.getFragmentList();
    138   SectionData::FragmentListType& to_list = pTo.getFragmentList();
    139   SectionData::FragmentListType::iterator frag, fragEnd = from_list.end();
    140   for (frag = from_list.begin(); frag != fragEnd; ++frag) {
    141     frag->setParent(&pTo);
    142     frag->setOffset(offset);
    143     offset += frag->size();
    144   }
    145   to_list.splice(to_list.end(), from_list);
    146 
    147   // set up pTo's header
    148   pTo.getSection().setSize(offset);
    149 
    150   return true;
    151 }
    152 
    153 /// UpdateSectionAlign - update alignment for input section
    154 void ObjectBuilder::UpdateSectionAlign(LDSection& pTo, const LDSection& pFrom)
    155 {
    156   if (pFrom.align() > pTo.align())
    157     pTo.setAlign(pFrom.align());
    158 }
    159 
    160 /// UpdateSectionAlign - update alignment for input section
    161 void ObjectBuilder::UpdateSectionAlign(LDSection& pSection,
    162                                        uint32_t pAlignConstraint)
    163 {
    164   if (pSection.align() < pAlignConstraint)
    165     pSection.setAlign(pAlignConstraint);
    166 }
    167 
    168 /// AppendFragment - To append pFrag to the given SectionData pSD.
    169 uint64_t ObjectBuilder::AppendFragment(Fragment& pFrag,
    170                                        SectionData& pSD,
    171                                        uint32_t pAlignConstraint)
    172 {
    173   // get initial offset.
    174   uint64_t offset = 0;
    175   if (!pSD.empty())
    176     offset = pSD.back().getOffset() + pSD.back().size();
    177 
    178   AlignFragment* align = NULL;
    179   if (pAlignConstraint > 1) {
    180     // if the align constraint is larger than 1, append an alignment
    181     align = new AlignFragment(pAlignConstraint, // alignment
    182                               0x0, // the filled value
    183                               1u,  // the size of filled value
    184                               pAlignConstraint - 1 // max bytes to emit
    185                               );
    186     align->setOffset(offset);
    187     align->setParent(&pSD);
    188     pSD.getFragmentList().push_back(align);
    189     offset += align->size();
    190   }
    191 
    192   // append the fragment
    193   pFrag.setParent(&pSD);
    194   pFrag.setOffset(offset);
    195   pSD.getFragmentList().push_back(&pFrag);
    196 
    197   // append the null fragment
    198   offset += pFrag.size();
    199   NullFragment* null = new NullFragment(&pSD);
    200   null->setOffset(offset);
    201 
    202   if (NULL != align)
    203     return align->size() + pFrag.size();
    204   else
    205     return pFrag.size();
    206 }
    207 
    208