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 
getRegion()64     const llvm::StringRef getRegion() const {
65       return RegionFragment::getRegion();
66     }
getRegion()67     llvm::StringRef getRegion() { return RegionFragment::getRegion(); }
getRecordType()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 
getRecordType()84     virtual RecordType getRecordType() const { return RECORD_INPUT; }
85 
setFDEEncode(uint8_t pEncode)86     void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; }
getFDEEncode()87     uint8_t getFDEEncode() const { return m_FDEEncode; }
88 
89     void setMergeable(bool pVal = true) { m_Mergeable = pVal; }
getMergeable()90     virtual bool getMergeable() const { return m_Mergeable; }
91 
setRelocation(const Relocation & pReloc)92     void setRelocation(const Relocation& pReloc) { m_pReloc = &pReloc; }
getRelocation()93     const Relocation* getRelocation() const { return m_pReloc; }
94 
setPersonalityOffset(uint64_t pOffset)95     void setPersonalityOffset(uint64_t pOffset) {
96       m_PersonalityOffset = pOffset;
97     }
getPersonalityOffset()98     uint64_t getPersonalityOffset() const { return m_PersonalityOffset; }
99 
setPersonalityName(const std::string & pStr)100     void setPersonalityName(const std::string& pStr) {
101       m_PersonalityName = pStr;
102     }
getPersonalityName()103     const std::string& getPersonalityName() const { return m_PersonalityName; }
104 
setAugmentationData(const std::string & pStr)105     void setAugmentationData(const std::string& pStr) {
106       m_AugmentationData = pStr;
107     }
getAugmentationData()108     const std::string& getAugmentationData() const {
109       return m_AugmentationData;
110     }
111 
add(FDE & pFDE)112     void add(FDE& pFDE) { m_FDEs.push_back(&pFDE); }
remove(FDE & pFDE)113     void remove(FDE& pFDE) { m_FDEs.remove(&pFDE); }
clearFDEs()114     void clearFDEs() { m_FDEs.clear(); }
numOfFDEs()115     size_t numOfFDEs() const { return m_FDEs.size(); }
116 
begin()117     const_fde_iterator begin() const { return m_FDEs.begin(); }
begin()118     fde_iterator begin() { return m_FDEs.begin(); }
end()119     const_fde_iterator end() const { return m_FDEs.end(); }
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);
getCIE()143     const CIE& getCIE() const { return *m_pCIE; }
getCIE()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 
getRecordType()156     virtual RecordType getRecordType() const { return RECORD_GENERATED; }
getMergeable()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 
getRecordType()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 
getSectionData()181   const SectionData* getSectionData() const { return m_pSectionData; }
getSectionData()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  ----- //
cie_begin()194   const_cie_iterator cie_begin() const { return m_CIEs.begin(); }
cie_begin()195   cie_iterator cie_begin() { return m_CIEs.begin(); }
cie_end()196   const_cie_iterator cie_end() const { return m_CIEs.end(); }
cie_end()197   cie_iterator cie_end() { return m_CIEs.end(); }
198 
cie_front()199   const CIE& cie_front() const { return *m_CIEs.front(); }
cie_front()200   CIE& cie_front() { return *m_CIEs.front(); }
cie_back()201   const CIE& cie_back() const { return *m_CIEs.back(); }
cie_back()202   CIE& cie_back() { return *m_CIEs.back(); }
203 
emptyCIEs()204   bool emptyCIEs() const { return m_CIEs.empty(); }
numOfCIEs()205   size_t numOfCIEs() const { return m_CIEs.size(); }
206   size_t numOfFDEs() const;
207 
getCIEMap()208   const CIEMap& getCIEMap() const { return m_FoundCIEs; }
getCIEMap()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>
getDataStartOffset()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