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 "mcld/LD/LDSection.h"
13 
14 #include <llvm/ADT/PointerUnion.h>
15 #include <llvm/ADT/StringRef.h>
16 #include <llvm/Support/ELF.h>
17 
18 #include <map>
19 #include <memory>
20 #include <string>
21 
22 namespace mcld {
23 
24 class Fragment;
25 class Input;
26 class LDSection;
27 class Module;
28 class RegionFragment;
29 class RelocData;
30 
31 /// ARMExSectionTuple - Tuple of associated exception handling sections
32 class ARMExSectionTuple {
33  public:
ARMExSectionTuple()34   ARMExSectionTuple()
35       : m_pTextSection(NULL),
36         m_pExIdxSection(NULL) {
37   }
38 
getTextSection()39   LDSection* getTextSection() const {
40     return m_pTextSection;
41   }
42 
getExIdxSection()43   LDSection* getExIdxSection() const {
44     return m_pExIdxSection;
45   }
46 
setTextSection(LDSection * pSection)47   void setTextSection(LDSection* pSection) {
48     m_pTextSection = pSection;
49   }
50 
setExIdxSection(LDSection * pSection)51   void setExIdxSection(LDSection* pSection) {
52     m_pExIdxSection = pSection;
53   }
54 
getTextFragment()55   RegionFragment* getTextFragment() const {
56     return m_pTextFragment;
57   }
58 
getExIdxFragment()59   RegionFragment* getExIdxFragment() const {
60     return m_pExIdxFragment;
61   }
62 
setTextFragment(RegionFragment * pFragment)63   void setTextFragment(RegionFragment* pFragment) {
64     m_pTextFragment = pFragment;
65   }
66 
setExIdxFragment(RegionFragment * pFragment)67   void setExIdxFragment(RegionFragment* pFragment) {
68     m_pExIdxFragment = pFragment;
69   }
70 
71  private:
72   // .text section
73   union {
74     LDSection*      m_pTextSection;
75     RegionFragment* m_pTextFragment;
76   };
77 
78   // .ARM.exidx section
79   union {
80     LDSection*      m_pExIdxSection;
81     RegionFragment* m_pExIdxFragment;
82   };
83 };
84 
85 /// ARMInputExMap - ARM exception handling section mapping of a mcld::Input.
86 class ARMInputExMap {
87  public:
88   typedef std::map<LDSection*, std::unique_ptr<ARMExSectionTuple> > SectMap;
89   typedef SectMap::iterator iterator;
90   typedef SectMap::const_iterator const_iterator;
91 
92  public:
93   // create - Build the exception handling section mapping of a mcld::Input.
94   static std::unique_ptr<ARMInputExMap> create(Input &input);
95 
96   /// getByExSection - Get the ARMExSectionTuple by the address of the
97   /// .ARM.exidx section.
getByExSection(LDSection & pSect)98   ARMExSectionTuple* getByExSection(LDSection &pSect) const {
99     assert(pSect.type() == llvm::ELF::SHT_ARM_EXIDX);
100     SectMap::const_iterator it = m_SectToExData.find(&pSect);
101     if (it == m_SectToExData.end()) {
102       return NULL;
103     }
104     return it->second.get();
105   }
106 
107   /// getOrCreate - Get an existing or create a new ARMExSectionTuple which is
108   /// associated with the address of the .ARM.exidx section.
getOrCreateByExSection(LDSection & pSect)109   ARMExSectionTuple* getOrCreateByExSection(LDSection &pSect) {
110     assert(pSect.type() == llvm::ELF::SHT_ARM_EXIDX);
111     std::unique_ptr<ARMExSectionTuple>& result = m_SectToExData[&pSect];
112     if (!result) {
113       result.reset(new ARMExSectionTuple());
114     }
115     return result.get();
116   }
117 
118   /// begin - return the iterator to the begin of the map
begin()119   iterator       begin()       { return m_SectToExData.begin(); }
begin()120   const_iterator begin() const { return m_SectToExData.begin(); }
121 
122   /// end - return the iterator to the end of the map
end()123   iterator       end()       { return m_SectToExData.end(); }
end()124   const_iterator end() const { return m_SectToExData.end(); }
125 
126   /// erase - remove an entry from the map
erase(iterator it)127   void erase(iterator it) { m_SectToExData.erase(it); }
128 
129  private:
130   ARMInputExMap() = default;
131 
132  private:
133   SectMap m_SectToExData;
134 };
135 
136 /// ARMExData - ARM exception handling data of a mcld::Module.
137 class ARMExData {
138  private:
139   typedef std::map<Input*, std::unique_ptr<ARMInputExMap> > InputMap;
140 
141   typedef std::map<const Fragment*, ARMExSectionTuple*> ExIdxMap;
142 
143  public:
144   // create - Build the exception handling section mapping of a mcld::Module.
145   static std::unique_ptr<ARMExData> create(Module &module);
146 
147   // addInputMap - register the ARMInputExMap with associated pInput
148   void addInputMap(Input* pInput,
149                    std::unique_ptr<ARMInputExMap> pExMap);
150 
151   // getInputMap - get the ARMInputExMap corresponding to pInput
getInputMap(Input * pInput)152   ARMInputExMap* getInputMap(Input* pInput) const {
153     InputMap::const_iterator it = m_Inputs.find(pInput);
154     if (it == m_Inputs.end()) {
155       return NULL;
156     }
157     return it->second.get();
158   }
159 
160   // getTupleByExIdx - get the ARMExSectionTuple corresponding to pExIdxFragment
getTupleByExIdx(const Fragment * pExIdxFragment)161   ARMExSectionTuple* getTupleByExIdx(const Fragment* pExIdxFragment) const {
162     ExIdxMap::const_iterator it = m_ExIdxToTuple.find(pExIdxFragment);
163     if (it == m_ExIdxToTuple.end()) {
164       return NULL;
165     }
166     return it->second;
167   }
168 
169  private:
170   ARMExData() = default;
171 
172  private:
173   // Map from Input to ARMInputExMap
174   InputMap m_Inputs;
175 
176   // Map from .ARM.exidx RegionFragment to ARMExSectionTuple
177   ExIdxMap m_ExIdxToTuple;
178 };
179 
180 }  // namespace mcld
181 
182 #endif  // TARGET_ARM_ARMEXCEPTION_H_
183