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
23namespace mcld {
24
25class Input;
26class Module;
27class LDSection;
28class ObjectLinker;
29class Relocation;
30
31/** \class EhFrame
32 *  \brief EhFrame represents .eh_frame section
33 */
34class EhFrame
35{
36private:
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
47public:
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
171public:
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
214public:
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
223private:
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
231private:
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
237private:
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
253bool operator==(const EhFrame::CIE&, const EhFrame::CIE&);
254
255} // namespace of mcld
256
257#endif
258
259