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 
19 namespace mcld {
20 
21 class Fragment;
22 class Input;
23 class LDSection;
24 class RegionFragment;
25 class RelocData;
26 
27 /// ARMExSectionTuple - Tuple of associated exception handling sections
28 class ARMExSectionTuple {
29  public:
ARMExSectionTuple()30   ARMExSectionTuple()
31       : m_pTextSection(NULL),
32         m_pExIdxSection(NULL),
33         m_pExTabSection(NULL),
34         m_pRelExIdxSection(NULL),
35         m_pRelExTabSection(NULL) {
36   }
37 
getTextSection()38   LDSection* getTextSection() const {
39     return m_pTextSection;
40   }
41 
getExIdxSection()42   LDSection* getExIdxSection() const {
43     return m_pExIdxSection;
44   }
45 
getExTabSection()46   LDSection* getExTabSection() const {
47     return m_pExTabSection;
48   }
49 
getRelExIdxSection()50   LDSection* getRelExIdxSection() const {
51     return m_pRelExIdxSection;
52   }
53 
getRelExTabSection()54   LDSection* getRelExTabSection() const {
55     return m_pRelExTabSection;
56   }
57 
setTextSection(LDSection * pSection)58   void setTextSection(LDSection* pSection) {
59     m_pTextSection = pSection;
60   }
61 
setExIdxSection(LDSection * pSection)62   void setExIdxSection(LDSection* pSection) {
63     m_pExIdxSection = pSection;
64   }
65 
setExTabSection(LDSection * pSection)66   void setExTabSection(LDSection* pSection) {
67     m_pExTabSection = pSection;
68   }
69 
setRelExIdxSection(LDSection * pSection)70   void setRelExIdxSection(LDSection* pSection) {
71     m_pRelExIdxSection = pSection;
72   }
73 
setRelExTabSection(LDSection * pSection)74   void setRelExTabSection(LDSection* pSection) {
75     m_pRelExTabSection = pSection;
76   }
77 
getTextFragment()78   RegionFragment* getTextFragment() const {
79     return m_pTextFragment;
80   }
81 
getExIdxFragment()82   RegionFragment* getExIdxFragment() const {
83     return m_pExIdxFragment;
84   }
85 
getExTabFragment()86   RegionFragment* getExTabFragment() const {
87     return m_pExTabFragment;
88   }
89 
getExIdxRelocData()90   RelocData* getExIdxRelocData() const {
91     return m_pExIdxRelocData;
92   }
93 
getExTabRelocData()94   RelocData* getExTabRelocData() const {
95     return m_pExTabRelocData;
96   }
97 
setTextFragment(RegionFragment * pFragment)98   void setTextFragment(RegionFragment* pFragment) {
99     m_pTextFragment = pFragment;
100   }
101 
setExIdxFragment(RegionFragment * pFragment)102   void setExIdxFragment(RegionFragment* pFragment) {
103     m_pExIdxFragment = pFragment;
104   }
105 
setExTabFragment(RegionFragment * pFragment)106   void setExTabFragment(RegionFragment* pFragment) {
107     m_pExTabFragment = pFragment;
108   }
109 
setExIdxRelocData(RelocData * pRelocData)110   void setExIdxRelocData(RelocData* pRelocData) {
111     m_pExIdxRelocData = pRelocData;
112   }
113 
setExTabRelocData(RelocData * pRelocData)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
151 class 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:
ARMInputExMap()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.
get(const char * pName)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 
getByExSection(llvm::StringRef pName)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 
getByRelExSection(llvm::StringRef pName)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.
getOrCreate(const char * pName)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 
getOrCreateByExSection(llvm::StringRef pName)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 
getOrCreateByRelExSection(llvm::StringRef pName)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
begin()211   iterator       begin()       { return m_NameToExData.begin(); }
begin()212   const_iterator begin() const { return m_NameToExData.begin(); }
213 
214   /// end - return the iterator to the end of the map
end()215   iterator       end()       { return m_NameToExData.end(); }
end()216   const_iterator end() const { return m_NameToExData.end(); }
217 
218   /// erase - remove an entry from the map
erase(iterator it)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
226 class 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:
ARMExData()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
getInputMap(Input * 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
getTupleByExIdx(const Fragment * 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