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