Home | History | Annotate | Download | only in LD
      1 //===- Layout.h -----------------------------------------------------------===//
      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 #ifndef MCLD_LAYOUT_H
     10 #define MCLD_LAYOUT_H
     11 #ifdef ENABLE_UNITTEST
     12 #include <gtest.h>
     13 #endif
     14 #include <llvm/ADT/ilist.h>
     15 #include <llvm/ADT/ilist_node.h>
     16 #include <llvm/ADT/DenseMap.h>
     17 #include <llvm/MC/MCAssembler.h>
     18 #include <mcld/MC/MCFragmentRef.h>
     19 #include <mcld/Support/GCFactory.h>
     20 #include <mcld/LD/LDSection.h>
     21 #include <map>
     22 
     23 namespace mcld
     24 {
     25 class MCLinker;
     26 class Output;
     27 class TargetLDBackend;
     28 
     29 /** \class Layout
     30  *  \brief Layout maintains the mapping between sections and fragments.
     31  *
     32  *  MCLinker is a fragment-based linker. But readers and target backends
     33  *  still need section information. Layout is used to maintain the mapping
     34  *  between sections and fragments. Layout helps readers and target backends
     35  *  get the input or output section information from a fragment.
     36  */
     37 class Layout
     38 {
     39 public:
     40   typedef std::vector<LDSection*> SectionOrder;
     41   typedef SectionOrder::iterator sect_iterator;
     42   typedef SectionOrder::const_iterator const_sect_iterator;
     43 
     44 public:
     45   /// constructor
     46   Layout();
     47 
     48   /// destructor
     49   ~Layout();
     50 
     51   /// getInputLDSection - give a MCFragment, return the corresponding input
     52   /// LDSection*
     53   ///
     54   /// @return return NULL if the fragment is not found in input
     55   LDSection* getInputLDSection(const llvm::MCFragment& pFrag);
     56 
     57   /// getInputLDSection - give a MCFragment, return the corresponding input
     58   /// LDSection*
     59   ///
     60   /// @return return NULL if the fragment is not found in input
     61   const LDSection* getInputLDSection(const llvm::MCFragment& pFrag) const;
     62 
     63   /// getFragmentRef - give a LDSection in input file and an offset, return
     64   /// the fragment reference.
     65   ///
     66   /// @param pInputSection - the given input section
     67   /// @param pOffset - the offset, cannot be larger than this input section.
     68   /// @return if found, return the fragment. Otherwise, return NULL.
     69   MCFragmentRef*
     70   getFragmentRef(const LDSection& pInputSection, uint64_t pOffset);
     71 
     72   /// getFragmentRef - give a fragment and a big offset, return the fragment
     73   /// reference in the section data.
     74   ///
     75   /// @param pFrag - the given fragment
     76   /// @param pBigOffset - the offset, can be larger than the fragment, but can
     77   ///                     not larger than this input section.
     78   /// @return if found, return the fragment. Otherwise, return NULL.
     79   MCFragmentRef*
     80   getFragmentRef(const llvm::MCFragment& pFrag, uint64_t pBigOffset);
     81 
     82   /// getOutputOffset - Get the offset of the given fragment inside the
     83   /// the output's MCSectionData.
     84   uint64_t getOutputOffset(const llvm::MCFragment& pFrag);
     85 
     86   /// getOutputOffset - Get the offset of the given fragment inside the
     87   /// the output's MCSectionData.
     88   uint64_t getOutputOffset(const llvm::MCFragment& pFrag) const;
     89 
     90   /// getOutputOffset - Get the offset of the given fragment inside
     91   /// the output's MCSectionData.
     92   ///
     93   /// @return return -1 if the fragment is not found in output's MCSectionData.
     94 
     95   uint64_t getOutputOffset(const MCFragmentRef& pFragRef);
     96   /// getOutputOffset - Get the offset of the given fragment inside
     97   /// the output's MCSectionData.
     98   ///
     99   /// @return return -1 if the fragment is not found in output's MCSectionData.
    100   uint64_t getOutputOffset(const MCFragmentRef& pFragRef) const;
    101 
    102   /// getOutputLDSection - give a MCFragment, return the corresponding output
    103   /// LDSection*
    104   ///
    105   /// @return return NULL if the fragment is not found in the output
    106   LDSection* getOutputLDSection(const llvm::MCFragment& pFrag);
    107 
    108   /// getOutputLDSection - give a MCFragment, return the corresponding output
    109   /// LDSection*
    110   ///
    111   /// @return return NULL if the fragment is not found in the output
    112   const LDSection* getOutputLDSection(const llvm::MCFragment& pFrag) const;
    113 
    114   // -----  modifiers  ----- //
    115   bool layout(Output& pOutput, const TargetLDBackend& pBackend);
    116 
    117   /// addInputRange
    118   void addInputRange(const llvm::MCSectionData& pSD,
    119                      const LDSection& pInputHdr);
    120 
    121   /// appendFragment - append the given MCFragment to the given MCSectionData,
    122   /// and insert a MCAlignFragment to preserve the required align constraint if
    123   /// needed
    124   /// @return return the inserted size, i.e., the size of pFrag and alignment
    125   /// size if any
    126   uint64_t appendFragment(llvm::MCFragment& pFrag,
    127                           llvm::MCSectionData& pSD,
    128                           uint32_t pAlignConstraint = 1);
    129 private:
    130   /** \class Range
    131    *  \brief Range is a <input's LDSection, previous rear fragment> pair
    132    */
    133   struct Range : public llvm::ilist_node<Range>
    134   {
    135   public:
    136     Range();
    137     Range(const LDSection& pHeader);
    138     ~Range();
    139 
    140   public:
    141     LDSection* header;
    142     llvm::MCFragment* prevRear;
    143   };
    144 
    145   typedef llvm::iplist<Range> RangeList;
    146 
    147   typedef std::map<const llvm::MCSectionData*, RangeList*> SDRangeMap;
    148 
    149   typedef GCFactory<MCFragmentRef, 0> FragRefFactory;
    150 
    151 private:
    152   inline bool isFirstRange(const Range& pRange) const
    153   { return (NULL == pRange.prevRear); }
    154 
    155   inline bool isLastRange(const Range& pRange) const
    156   { return (NULL == pRange.getNextNode()); }
    157 
    158   inline bool isEmptyRange(const Range& pRange) const
    159   {
    160     if (isFirstRange(pRange)) {
    161       if (!pRange.header->hasSectionData() ||
    162           pRange.header->getSectionData()->getFragmentList().empty())
    163         return true;
    164       else
    165         return false;
    166     }
    167     return (NULL == pRange.prevRear->getNextNode());
    168   }
    169 
    170   // get the front fragment in the range.
    171   inline llvm::MCFragment* getFront(Range& pRange) const
    172   {
    173     if (!pRange.header->hasSectionData())
    174       return NULL;
    175     if (pRange.header->getSectionData()->getFragmentList().empty())
    176       return NULL;
    177 
    178     if (isFirstRange(pRange))
    179       return &pRange.header->getSectionData()->getFragmentList().front();
    180 
    181     if (isEmptyRange(pRange))
    182       return NULL;
    183 
    184     return pRange.prevRear->getNextNode();
    185   }
    186 
    187   inline const llvm::MCFragment* getFront(const Range& pRange) const
    188   {
    189     if (!pRange.header->hasSectionData())
    190       return NULL;
    191     if (pRange.header->getSectionData()->getFragmentList().empty())
    192       return NULL;
    193 
    194     if (isFirstRange(pRange))
    195       return &pRange.header->getSectionData()->getFragmentList().front();
    196 
    197     if (isEmptyRange(pRange))
    198       return NULL;
    199 
    200     return pRange.prevRear->getNextNode();
    201   }
    202 
    203   // get the rear fragment in the range.
    204   inline llvm::MCFragment* getRear(Range& pRange) const
    205   {
    206     if (!pRange.header->hasSectionData())
    207       return NULL;
    208     if (pRange.header->getSectionData()->getFragmentList().empty())
    209       return NULL;
    210 
    211     if (isLastRange(pRange)) {
    212       if (isEmptyRange(pRange))
    213         return NULL;
    214       return &pRange.header->getSectionData()->getFragmentList().back();
    215     }
    216     return pRange.getNextNode()->prevRear;
    217   }
    218 
    219   inline const llvm::MCFragment* getRear(const Range& pRange) const
    220   {
    221     if (!pRange.header->hasSectionData())
    222       return NULL;
    223     if (pRange.header->getSectionData()->getFragmentList().empty())
    224       return NULL;
    225 
    226     if (isLastRange(pRange)) {
    227       if (isEmptyRange(pRange))
    228         return NULL;
    229       return &pRange.header->getSectionData()->getFragmentList().back();
    230     }
    231     return pRange.getNextNode()->prevRear;
    232   }
    233 
    234   MCFragmentRef* getFragmentRef(Range &pRange, uint64_t pOffset);
    235 
    236   MCFragmentRef* getFragmentRef(llvm::MCFragment& pFront,
    237                                 llvm::MCFragment& pRear,
    238                                 uint64_t pOffset);
    239 
    240   bool hasLayoutOrder(const llvm::MCFragment& pFragment) const
    241   { return (pFragment.getLayoutOrder() != ~(0U)); }
    242 
    243   bool hasLayoutOffset(const llvm::MCFragment& pFragment) const
    244   { return (pFragment.Offset != ~UINT64_C(0)); }
    245 
    246   bool isValidOffset(const llvm::MCFragment& pFrag, uint64_t pTargetOffset) const;
    247 
    248   void setFragmentLayoutOrder(llvm::MCFragment* pFragment);
    249 
    250   void setFragmentLayoutOffset(llvm::MCFragment* pFragment);
    251 
    252   /// sortSectionOrder - perform sorting on m_SectionOrder to get final layout
    253   /// ordering
    254   void sortSectionOrder(const Output& pOutput,
    255                         const TargetLDBackend& pBackend);
    256 
    257 private:
    258   /// a vector to describe the order of sections
    259   SectionOrder m_SectionOrder;
    260 
    261   /// the map from MCSectionData* to its own RangeList.
    262   SDRangeMap m_SDRangeMap;
    263 
    264   FragRefFactory m_FragRefFactory;
    265 };
    266 
    267 } // namespace of mcld
    268 
    269 #endif
    270