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
24namespace mcld {
25
26class Input;
27class LDSection;
28class Relocation;
29
30/** \class EhFrame
31 *  \brief EhFrame represents .eh_frame section
32 */
33class 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
257bool operator==(const EhFrame::CIE&, const EhFrame::CIE&);
258
259}  // namespace mcld
260
261#endif  // MCLD_LD_EHFRAME_H_
262