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