Home | History | Annotate | Download | only in LD
      1 //===- EhFrame.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_LD_EHFRAME_H_
     10 #define MCLD_LD_EHFRAME_H_
     11 
     12 #include "mcld/Config/Config.h"
     13 #include "mcld/Fragment/RegionFragment.h"
     14 #include "mcld/LD/SectionData.h"
     15 #include "mcld/Support/Allocators.h"
     16 #include "mcld/Support/Compiler.h"
     17 
     18 #include <llvm/ADT/StringRef.h>
     19 
     20 #include <list>
     21 #include <map>
     22 #include <vector>
     23 
     24 namespace mcld {
     25 
     26 class Input;
     27 class LDSection;
     28 class Relocation;
     29 
     30 /** \class EhFrame
     31  *  \brief EhFrame represents .eh_frame section
     32  */
     33 class EhFrame {
     34  private:
     35   friend class Chunk<EhFrame, MCLD_SECTIONS_PER_INPUT>;
     36 
     37   EhFrame();
     38   explicit EhFrame(LDSection& pSection);
     39 
     40   ~EhFrame();
     41 
     42  public:
     43   enum RecordType { RECORD_UNKNOWN, RECORD_INPUT, RECORD_GENERATED };
     44 
     45   class CIE;
     46   class FDE;
     47 
     48   typedef std::vector<CIE*> CIEList;
     49   typedef CIEList::iterator cie_iterator;
     50   typedef CIEList::const_iterator const_cie_iterator;
     51 
     52   typedef std::list<FDE*> FDEList;
     53   typedef FDEList::iterator fde_iterator;
     54   typedef FDEList::const_iterator const_fde_iterator;
     55 
     56   typedef std::map</*offset*/ size_t, CIE*> CIEMap;
     57 
     58   // A super class of CIE and FDE, containing the same part
     59   class Record : public RegionFragment {
     60    public:
     61     explicit Record(llvm::StringRef pRegion);
     62     virtual ~Record();
     63 
     64     const llvm::StringRef getRegion() const {
     65       return RegionFragment::getRegion();
     66     }
     67     llvm::StringRef getRegion() { return RegionFragment::getRegion(); }
     68     virtual RecordType getRecordType() const { return RECORD_UNKNOWN; }
     69 
     70    private:
     71     DISALLOW_COPY_AND_ASSIGN(Record);
     72   };
     73 
     74   /** \class CIE
     75    *  \brief Common Information Entry.
     76    *  The CIE structure refers to LSB Core Spec 4.1, chap.10.6. Exception
     77    * Frames.
     78    */
     79   class CIE : public Record {
     80    public:
     81     explicit CIE(llvm::StringRef pRegion);
     82     ~CIE();
     83 
     84     virtual RecordType getRecordType() const { return RECORD_INPUT; }
     85 
     86     void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; }
     87     uint8_t getFDEEncode() const { return m_FDEEncode; }
     88 
     89     void setMergeable(bool pVal = true) { m_Mergeable = pVal; }
     90     virtual bool getMergeable() const { return m_Mergeable; }
     91 
     92     void setRelocation(const Relocation& pReloc) { m_pReloc = &pReloc; }
     93     const Relocation* getRelocation() const { return m_pReloc; }
     94 
     95     void setPersonalityOffset(uint64_t pOffset) {
     96       m_PersonalityOffset = pOffset;
     97     }
     98     uint64_t getPersonalityOffset() const { return m_PersonalityOffset; }
     99 
    100     void setPersonalityName(const std::string& pStr) {
    101       m_PersonalityName = pStr;
    102     }
    103     const std::string& getPersonalityName() const { return m_PersonalityName; }
    104 
    105     void setAugmentationData(const std::string& pStr) {
    106       m_AugmentationData = pStr;
    107     }
    108     const std::string& getAugmentationData() const {
    109       return m_AugmentationData;
    110     }
    111 
    112     void add(FDE& pFDE) { m_FDEs.push_back(&pFDE); }
    113     void remove(FDE& pFDE) { m_FDEs.remove(&pFDE); }
    114     void clearFDEs() { m_FDEs.clear(); }
    115     size_t numOfFDEs() const { return m_FDEs.size(); }
    116 
    117     const_fde_iterator begin() const { return m_FDEs.begin(); }
    118     fde_iterator begin() { return m_FDEs.begin(); }
    119     const_fde_iterator end() const { return m_FDEs.end(); }
    120     fde_iterator end() { return m_FDEs.end(); }
    121 
    122    private:
    123     uint8_t m_FDEEncode;
    124     bool m_Mergeable;
    125     const Relocation* m_pReloc;
    126     uint64_t m_PersonalityOffset;
    127     std::string m_PersonalityName;
    128     std::string m_AugmentationData;
    129     FDEList m_FDEs;
    130   };
    131 
    132   /** \class FDE
    133    *  \brief Frame Description Entry
    134    *  The FDE structure refers to LSB Core Spec 4.1, chap.10.6. Exception
    135    * Frames.
    136    */
    137   class FDE : public Record {
    138    public:
    139     FDE(llvm::StringRef pRegion, CIE& pCIE);
    140     ~FDE();
    141 
    142     void setCIE(CIE& pCIE);
    143     const CIE& getCIE() const { return *m_pCIE; }
    144     CIE& getCIE() { return *m_pCIE; }
    145 
    146    private:
    147     CIE* m_pCIE;  // Referenced CIE may change when merging.
    148   };
    149 
    150   // These are created for PLT
    151   class GeneratedCIE : public CIE {
    152    public:
    153     explicit GeneratedCIE(llvm::StringRef pRegion);
    154     ~GeneratedCIE();
    155 
    156     virtual RecordType getRecordType() const { return RECORD_GENERATED; }
    157     virtual bool getMergeable() const { return true; }
    158   };
    159 
    160   class GeneratedFDE : public FDE {
    161    public:
    162     GeneratedFDE(llvm::StringRef pRegion, CIE& pCIE);
    163     ~GeneratedFDE();
    164 
    165     virtual RecordType getRecordType() const { return RECORD_GENERATED; }
    166   };
    167 
    168  public:
    169   static EhFrame* Create(LDSection& pSection);
    170 
    171   static void Destroy(EhFrame*& pSection);
    172 
    173   static void Clear();
    174 
    175   /// merge - move all data from pOther to this object.
    176   EhFrame& merge(const Input& pInput, EhFrame& pInFrame);
    177 
    178   const LDSection& getSection() const;
    179   LDSection& getSection();
    180 
    181   const SectionData* getSectionData() const { return m_pSectionData; }
    182   SectionData* getSectionData() { return m_pSectionData; }
    183 
    184   // -----  fragment  ----- //
    185   void addFragment(Fragment& pFrag);
    186 
    187   /// addCIE - add a CIE entry in EhFrame
    188   void addCIE(CIE& pCIE, bool pAlsoAddFragment = true);
    189 
    190   /// addFDE - add a FDE entry in EhFrame
    191   void addFDE(FDE& pFDE, bool pAlsoAddFragment = true);
    192 
    193   // -----  CIE  ----- //
    194   const_cie_iterator cie_begin() const { return m_CIEs.begin(); }
    195   cie_iterator cie_begin() { return m_CIEs.begin(); }
    196   const_cie_iterator cie_end() const { return m_CIEs.end(); }
    197   cie_iterator cie_end() { return m_CIEs.end(); }
    198 
    199   const CIE& cie_front() const { return *m_CIEs.front(); }
    200   CIE& cie_front() { return *m_CIEs.front(); }
    201   const CIE& cie_back() const { return *m_CIEs.back(); }
    202   CIE& cie_back() { return *m_CIEs.back(); }
    203 
    204   bool emptyCIEs() const { return m_CIEs.empty(); }
    205   size_t numOfCIEs() const { return m_CIEs.size(); }
    206   size_t numOfFDEs() const;
    207 
    208   const CIEMap& getCIEMap() const { return m_FoundCIEs; }
    209   CIEMap& getCIEMap() { return m_FoundCIEs; }
    210 
    211  public:
    212   size_t computeOffsetSize();
    213 
    214   /// getDataStartOffset - Get the offset after length and ID field.
    215   /// The offset is 8byte for 32b, and 16byte for 64b.
    216   /// We can just use "BITCLASS/4" to represent offset.
    217   template <size_t BITCLASS>
    218   static size_t getDataStartOffset() {
    219     return BITCLASS / 4;
    220   }
    221 
    222  private:
    223   // We needs to check if it is mergeable and check personality name
    224   // before merging them. The important note is we must do this after
    225   // ALL readSections done, that is the reason why we don't check this
    226   // immediately when reading.
    227   void setupAttributes(const LDSection* reloc_sect);
    228   void removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocEhFrameSect);
    229 
    230  private:
    231   void removeAndUpdateCIEForFDE(EhFrame& pInFrame,
    232                                 CIE& pInCIE,
    233                                 CIE& pOutCIE,
    234                                 const LDSection* reloc_sect);
    235   void moveInputFragments(EhFrame& pInFrame);
    236   void moveInputFragments(EhFrame& pInFrame, CIE& pInCIE, CIE* pOutCIE = 0);
    237 
    238  private:
    239   LDSection* m_pSection;
    240   SectionData* m_pSectionData;
    241 
    242   // Each eh_frame has a list of CIE, and each CIE has a list of FDE
    243   // pointing to the CIE itself. This is used by management when we are
    244   // processing eh_frame merge.
    245   // However, don't forget we need to handle the Fragments inside SectionData
    246   // correctly since they are truly used when output emission.
    247   CIEList m_CIEs;
    248 
    249   // We need this map to find the corresponding CIE for FDE. Not all FDE point
    250   // to the nearest CIE.
    251   CIEMap m_FoundCIEs;
    252 
    253  private:
    254   DISALLOW_COPY_AND_ASSIGN(EhFrame);
    255 };
    256 
    257 bool operator==(const EhFrame::CIE&, const EhFrame::CIE&);
    258 
    259 }  // namespace mcld
    260 
    261 #endif  // MCLD_LD_EHFRAME_H_
    262