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