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
22namespace mcld {
23
24class Fragment;
25class Input;
26class LDSection;
27class Module;
28class RegionFragment;
29class RelocData;
30
31/// ARMExSectionTuple - Tuple of associated exception handling sections
32class ARMExSectionTuple {
33 public:
34  ARMExSectionTuple()
35      : m_pTextSection(NULL),
36        m_pExIdxSection(NULL) {
37  }
38
39  LDSection* getTextSection() const {
40    return m_pTextSection;
41  }
42
43  LDSection* getExIdxSection() const {
44    return m_pExIdxSection;
45  }
46
47  void setTextSection(LDSection* pSection) {
48    m_pTextSection = pSection;
49  }
50
51  void setExIdxSection(LDSection* pSection) {
52    m_pExIdxSection = pSection;
53  }
54
55  RegionFragment* getTextFragment() const {
56    return m_pTextFragment;
57  }
58
59  RegionFragment* getExIdxFragment() const {
60    return m_pExIdxFragment;
61  }
62
63  void setTextFragment(RegionFragment* pFragment) {
64    m_pTextFragment = pFragment;
65  }
66
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.
86class 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.
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.
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
119  iterator       begin()       { return m_SectToExData.begin(); }
120  const_iterator begin() const { return m_SectToExData.begin(); }
121
122  /// end - return the iterator to the end of the map
123  iterator       end()       { return m_SectToExData.end(); }
124  const_iterator end() const { return m_SectToExData.end(); }
125
126  /// erase - remove an entry from the map
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.
137class 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
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
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