ARMException.h revision a6c24dff8b7fa2551a3a885e77a2e814f5b764a2
1//===- ARMException.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 TARGET_ARM_ARMEXCEPTION_H_
10#define TARGET_ARM_ARMEXCEPTION_H_
11
12#include <llvm/ADT/PointerUnion.h>
13#include <llvm/ADT/StringRef.h>
14
15#include <map>
16#include <memory>
17#include <string>
18
19namespace mcld {
20
21class Fragment;
22class Input;
23class LDSection;
24class RegionFragment;
25class RelocData;
26
27/// ARMExSectionTuple - Tuple of associated exception handling sections
28class ARMExSectionTuple {
29 public:
30  ARMExSectionTuple()
31      : m_pTextSection(NULL),
32        m_pExIdxSection(NULL),
33        m_pExTabSection(NULL),
34        m_pRelExIdxSection(NULL),
35        m_pRelExTabSection(NULL) {
36  }
37
38  LDSection* getTextSection() const {
39    return m_pTextSection;
40  }
41
42  LDSection* getExIdxSection() const {
43    return m_pExIdxSection;
44  }
45
46  LDSection* getExTabSection() const {
47    return m_pExTabSection;
48  }
49
50  LDSection* getRelExIdxSection() const {
51    return m_pRelExIdxSection;
52  }
53
54  LDSection* getRelExTabSection() const {
55    return m_pRelExTabSection;
56  }
57
58  void setTextSection(LDSection* pSection) {
59    m_pTextSection = pSection;
60  }
61
62  void setExIdxSection(LDSection* pSection) {
63    m_pExIdxSection = pSection;
64  }
65
66  void setExTabSection(LDSection* pSection) {
67    m_pExTabSection = pSection;
68  }
69
70  void setRelExIdxSection(LDSection* pSection) {
71    m_pRelExIdxSection = pSection;
72  }
73
74  void setRelExTabSection(LDSection* pSection) {
75    m_pRelExTabSection = pSection;
76  }
77
78  RegionFragment* getTextFragment() const {
79    return m_pTextFragment;
80  }
81
82  RegionFragment* getExIdxFragment() const {
83    return m_pExIdxFragment;
84  }
85
86  RegionFragment* getExTabFragment() const {
87    return m_pExTabFragment;
88  }
89
90  RelocData* getExIdxRelocData() const {
91    return m_pExIdxRelocData;
92  }
93
94  RelocData* getExTabRelocData() const {
95    return m_pExTabRelocData;
96  }
97
98  void setTextFragment(RegionFragment* pFragment) {
99    m_pTextFragment = pFragment;
100  }
101
102  void setExIdxFragment(RegionFragment* pFragment) {
103    m_pExIdxFragment = pFragment;
104  }
105
106  void setExTabFragment(RegionFragment* pFragment) {
107    m_pExTabFragment = pFragment;
108  }
109
110  void setExIdxRelocData(RelocData* pRelocData) {
111    m_pExIdxRelocData = pRelocData;
112  }
113
114  void setExTabRelocData(RelocData* pRelocData) {
115    m_pExTabRelocData = pRelocData;
116  }
117
118 private:
119  // .text section
120  union {
121    LDSection*      m_pTextSection;
122    RegionFragment* m_pTextFragment;
123  };
124
125  // .ARM.exidx section
126  union {
127    LDSection*      m_pExIdxSection;
128    RegionFragment* m_pExIdxFragment;
129  };
130
131  // .ARM.extab section
132  union {
133    LDSection*      m_pExTabSection;
134    RegionFragment* m_pExTabFragment;
135  };
136
137  // .rel.ARM.exidx section
138  union {
139    LDSection*      m_pRelExIdxSection;
140    RelocData*      m_pExIdxRelocData;
141  };
142
143  // .rel.ARM.extab section
144  union {
145    LDSection*      m_pRelExTabSection;
146    RelocData*      m_pExTabRelocData;
147  };
148};
149
150/// ARMInputExMap - ARM exception handling data of an Input
151class ARMInputExMap {
152 public:
153  typedef std::map<std::string, std::unique_ptr<ARMExSectionTuple> > NameMap;
154  typedef NameMap::iterator iterator;
155  typedef NameMap::const_iterator const_iterator;
156
157 public:
158  ARMInputExMap() { }
159
160  /// get - Get the ARMExSectionTuple by the corresponding text section name.
161  /// As an exception, to get the ARMExSectionTuple for .text section, use ""
162  /// as the section name instead.
163  ARMExSectionTuple* get(const char* pName) const {
164    NameMap::const_iterator it = m_NameToExData.find(pName);
165    if (it == m_NameToExData.end()) {
166      return NULL;
167    }
168    return it->second.get();
169  }
170
171  ARMExSectionTuple* getByExSection(llvm::StringRef pName) const {
172    assert((pName.startswith(".ARM.exidx") ||
173            pName.startswith(".ARM.extab")) &&
174           "Not a .ARM.exidx section name");
175    return get(pName.data() + sizeof(".ARM.ex***") - 1);
176  }
177
178  ARMExSectionTuple* getByRelExSection(llvm::StringRef pName) const {
179    assert((pName.startswith(".rel.ARM.exidx") ||
180            pName.startswith(".rel.ARM.extab")) &&
181           "Not a .rel.ARM.exidx section name");
182    return get(pName.data() + sizeof(".rel.ARM.ex***") - 1);
183  }
184
185  /// getOrCreate - Get an existing or create a new ARMExSectionTuple which is
186  /// associated with the text section name.  As an exception, use "" as the
187  /// section name for .text section.
188  ARMExSectionTuple* getOrCreate(const char* pName) {
189    std::unique_ptr<ARMExSectionTuple>& result = m_NameToExData[pName];
190    if (!result) {
191      result.reset(new ARMExSectionTuple());
192    }
193    return result.get();
194  }
195
196  ARMExSectionTuple* getOrCreateByExSection(llvm::StringRef pName) {
197    assert((pName.startswith(".ARM.exidx") ||
198            pName.startswith(".ARM.extab")) &&
199           "Not a .ARM.exidx section name");
200    return getOrCreate(pName.data() + sizeof(".ARM.ex***") - 1);
201  }
202
203  ARMExSectionTuple* getOrCreateByRelExSection(llvm::StringRef pName) {
204    assert((pName.startswith(".rel.ARM.exidx") ||
205            pName.startswith(".rel.ARM.extab")) &&
206           "Not a .rel.ARM.exidx section name");
207    return getOrCreate(pName.data() + sizeof(".rel.ARM.ex***") - 1);
208  }
209
210  /// begin - return the iterator to the begin of the map
211  iterator       begin()       { return m_NameToExData.begin(); }
212  const_iterator begin() const { return m_NameToExData.begin(); }
213
214  /// end - return the iterator to the end of the map
215  iterator       end()       { return m_NameToExData.end(); }
216  const_iterator end() const { return m_NameToExData.end(); }
217
218  /// erase - remove an entry from the map
219  void erase(iterator it) { m_NameToExData.erase(it); }
220
221 private:
222  NameMap m_NameToExData;
223};
224
225/// ARMExData - ARM exception handling data of a module
226class ARMExData {
227 private:
228  typedef std::map<Input*, std::unique_ptr<ARMInputExMap> > InputMap;
229
230  typedef std::map<const Fragment*, ARMExSectionTuple*> ExIdxMap;
231
232 public:
233  ARMExData() { }
234
235  // addInputMap - register the ARMInputExMap with associated pInput
236  void addInputMap(Input* pInput,
237                   std::unique_ptr<ARMInputExMap>&& pExMap);
238
239  // getInputMap - get the ARMInputExMap corresponding to pInput
240  ARMInputExMap* getInputMap(Input* pInput) const {
241    InputMap::const_iterator it = m_Inputs.find(pInput);
242    if (it == m_Inputs.end()) {
243      return NULL;
244    }
245    return it->second.get();
246  }
247
248  // getTupleByExIdx - get the ARMExSectionTuple corresponding to pExIdxFragment
249  ARMExSectionTuple* getTupleByExIdx(const Fragment* pExIdxFragment) const {
250    ExIdxMap::const_iterator it = m_ExIdxToTuple.find(pExIdxFragment);
251    if (it == m_ExIdxToTuple.end()) {
252      return NULL;
253    }
254    return it->second;
255  }
256
257 private:
258  // Map from Input to ARMInputExMap
259  InputMap m_Inputs;
260
261  // Map from .ARM.exidx RegionFragment to ARMExSectionTuple
262  ExIdxMap m_ExIdxToTuple;
263};
264
265}  // namespace mcld
266
267#endif  // TARGET_ARM_ARMEXCEPTION_H_
268