1 // Copyright (C) 2013 The Android Open Source Project
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
6 // are met:
7 // 1. Redistributions of source code must retain the above copyright
8 //    notice, this list of conditions and the following disclaimer.
9 // 2. Redistributions in binary form must reproduce the above copyright
10 //    notice, this list of conditions and the following disclaimer in the
11 //    documentation and/or other materials provided with the distribution.
12 // 3. Neither the name of the project nor the names of its contributors
13 //    may be used to endorse or promote products derived from this software
14 //    without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 // SUCH DAMAGE.
27 
28 #ifndef _GABIXX_CXXABI_DEFINES_H
29 #define _GABIXX_CXXABI_DEFINES_H
30 
31 #include <cxxabi.h>
32 #include <stdint.h>
33 
34 // Internal declarations for the implementation of <cxxabi.h> and
35 // related headers.
36 
37 namespace __cxxabiv1 {
38 
39 // Derived types of type_info below are based on 2.9.5 of C++ ABI.
40 
41 class __shim_type_info : public std::type_info
42 {
43   public:
44   virtual ~__shim_type_info();
45   virtual bool can_catch(const __shim_type_info* thrown_type,
46                           void*& adjustedPtr) const = 0;
47 };
48 
49 // Typeinfo for fundamental types.
50 class __fundamental_type_info : public __shim_type_info
51 {
52 public:
53   virtual ~__fundamental_type_info();
54   virtual bool can_catch(const __shim_type_info* thrown_type,
55                           void*& adjustedPtr) const;
56 };
57 
58 // Typeinfo for array types.
59 class __array_type_info : public __shim_type_info
60 {
61 public:
62   virtual ~__array_type_info();
63   virtual bool can_catch(const __shim_type_info* thrown_type,
64                           void*& adjustedPtr) const;
65 };
66 
67 // Typeinfo for function types.
68 class __function_type_info : public __shim_type_info
69 {
70 public:
71   virtual ~__function_type_info();
72   virtual bool can_catch(const __shim_type_info* thrown_type,
73                           void*& adjustedPtr) const;
74 };
75 
76 // Typeinfo for enum types.
77 class __enum_type_info : public __shim_type_info
78 {
79 public:
80   virtual ~__enum_type_info();
81   virtual bool can_catch(const __shim_type_info* thrown_type,
82                           void*& adjustedPtr) const;
83 };
84 
85 
86 class __class_type_info;
87 
88 // Used in __vmi_class_type_info
89 struct __base_class_type_info
90 {
91 public:
92   const __class_type_info *__base_type;
93 
94   long __offset_flags;
95 
96   enum __offset_flags_masks {
97     __virtual_mask = 0x1,
98     __public_mask = 0x2,
99     __offset_shift = 8   // lower 8 bits are flags
100   };
101 
is_virtual__base_class_type_info102   bool is_virtual() const {
103     return (__offset_flags & __virtual_mask) != 0;
104   }
105 
is_public__base_class_type_info106   bool is_public() const {
107     return (__offset_flags & __public_mask) != 0;
108   }
109 
110   // FIXME: Right-shift of signed integer is implementation dependent.
111   // GCC Implements it as signed (as we expect)
offset__base_class_type_info112   long offset() const {
113     return __offset_flags >> __offset_shift;
114   }
115 
flags__base_class_type_info116   long flags() const {
117     return __offset_flags & ((1 << __offset_shift) - 1);
118   }
119 };
120 
121 // Helper struct to support catch-clause match
122 struct __UpcastInfo {
123   enum ContainedStatus {
124     unknown = 0,
125     has_public_contained,
126     has_ambig_or_not_public
127   };
128 
129   ContainedStatus status;
130   const __class_type_info* base_type;
131   void* adjustedPtr;
132   unsigned int premier_flags;
133   bool nullobj_may_conflict;
134 
135   __UpcastInfo(const __class_type_info* type);
136 };
137 
138 // Typeinfo for classes with no bases.
139 class __class_type_info : public __shim_type_info
140 {
141 public:
142   virtual ~__class_type_info();
143   virtual bool can_catch(const __shim_type_info* thrown_type,
144                           void*& adjustedPtr) const;
145 
146   enum class_type_info_code {
147     CLASS_TYPE_INFO_CODE,
148     SI_CLASS_TYPE_INFO_CODE,
149     VMI_CLASS_TYPE_INFO_CODE
150   };
151 
152   virtual class_type_info_code
code()153     code() const { return CLASS_TYPE_INFO_CODE; }
154 
155   virtual bool walk_to(const __class_type_info* base_type,
156                         void*& adjustedPtr,
157                         __UpcastInfo& info) const;
158 
159 protected:
160   bool self_class_type_match(const __class_type_info* base_type,
161                               void*& adjustedPtr,
162                               __UpcastInfo& info) const;
163 };
164 
165 // Typeinfo for classes containing only a single, public, non-virtual base at
166 // offset zero.
167 class __si_class_type_info : public __class_type_info
168 {
169 public:
170   virtual ~__si_class_type_info();
171   const __class_type_info *__base_type;
172 
173   virtual __class_type_info::class_type_info_code
code()174     code() const { return SI_CLASS_TYPE_INFO_CODE; }
175 
176   virtual bool walk_to(const __class_type_info* base_type,
177                         void*& adjustedPtr,
178                         __UpcastInfo& info) const;
179 };
180 
181 
182 // Typeinfo for classes with bases that do not satisfy the
183 // __si_class_type_info constraints.
184 class __vmi_class_type_info : public __class_type_info
185 {
186 public:
187   virtual ~__vmi_class_type_info();
188   unsigned int __flags;
189   unsigned int __base_count;
190   __base_class_type_info __base_info[1];
191 
192   enum __flags_masks {
193     __non_diamond_repeat_mask = 0x1,
194     __diamond_shaped_mask = 0x2,
195   };
196 
197   virtual __class_type_info::class_type_info_code
code()198     code() const { return VMI_CLASS_TYPE_INFO_CODE; }
199 
200   virtual bool walk_to(const __class_type_info* base_type,
201                         void*& adjustedPtr,
202                         __UpcastInfo& info) const;
203 };
204 
205 class __pbase_type_info : public __shim_type_info
206 {
207 public:
208   virtual ~__pbase_type_info();
209   virtual bool can_catch(const __shim_type_info* thrown_type,
210                           void*& adjustedPtr) const;
211   unsigned int __flags;
212   const __shim_type_info* __pointee;
213 
214   enum __masks {
215     __const_mask = 0x1,
216     __volatile_mask = 0x2,
217     __restrict_mask = 0x4,
218     __incomplete_mask = 0x8,
219     __incomplete_class_mask = 0x10
220   };
221 
222 
223   virtual bool can_catch_typeinfo_wrapper(const __shim_type_info* thrown_type,
224                                           void*& adjustedPtr,
225                                           unsigned tracker) const;
226 
227 protected:
228   enum __constness_tracker_status {
229     first_time_init = 0x1,
230     keep_constness = 0x2,
231     after_gap = 0x4         // after one non-const qualified,
232                             // we cannot face const again in future
233   };
234 
235 private:
236   bool can_catch_ptr(const __pbase_type_info *thrown_type,
237                       void *&adjustedPtr,
238                       unsigned tracker) const;
239 
240   // Return true if making decision done.
241   virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
242                                 void*& adjustedPtr,
243                                 unsigned tracker,
244                                 bool& result) const = 0;
245 };
246 
247 class __pointer_type_info : public __pbase_type_info
248 {
249 public:
250   virtual ~__pointer_type_info();
251 
252 private:
253   virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
254                                 void*& adjustedPtr,
255                                 unsigned tracker,
256                                 bool& result) const;
257 };
258 
259 class __pointer_to_member_type_info : public __pbase_type_info
260 {
261 public:
262   __class_type_info* __context;
263 
264   virtual ~__pointer_to_member_type_info();
265 
266 private:
267   virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
268                                 void*& adjustedPtr,
269                                 unsigned tracker,
270                                 bool& result) const;
271 };
272 
273 extern "C" {
274 
275 // Compatible with GNU C++
276 const uint64_t __gxx_exception_class = 0x474E5543432B2B00LL; // GNUCC++\0
277 
278 struct __cxa_exception {
279   size_t referenceCount;
280 
281   std::type_info* exceptionType;
282   void (*exceptionDestructor)(void*);
283   std::unexpected_handler unexpectedHandler;
284   std::terminate_handler terminateHandler;
285   __cxa_exception* nextException;
286 
287     int handlerCount;
288 #ifdef __arm__
289   /**
290     * ARM EHABI requires the unwind library to keep track of exceptions
291     * during cleanups.  These support nesting, so we need to keep a list of
292     * them.
293     */
294   __cxa_exception* nextCleanup;
295   int cleanupCount;
296 #endif
297     int handlerSwitchValue;
298     const uint8_t* actionRecord;
299     const uint8_t* languageSpecificData;
300     void* catchTemp;
301     void* adjustedPtr;
302 
303     _Unwind_Exception unwindHeader; // must be last
304 };
305 
306 struct __cxa_eh_globals {
307   __cxa_exception* caughtExceptions;
308   unsigned int uncaughtExceptions;
309 #ifdef __arm__
310   __cxa_exception* cleanupExceptions;
311 #endif
312 };
313 
314 }  // extern "C"
315 }  // namespace __cxxabiv1
316 
317 namespace __gabixx {
318 
319 // Default unexpected handler.
320 _GABIXX_NORETURN void __default_unexpected(void) _GABIXX_HIDDEN;
321 
322 // Default terminate handler.
323 _GABIXX_NORETURN void __default_terminate(void) _GABIXX_HIDDEN;
324 
325 // Call |handler| and if it returns, call __default_terminate.
326 _GABIXX_NORETURN void __terminate(std::terminate_handler handler)
327     _GABIXX_HIDDEN;
328 
329 // Print a fatal error message to the log+stderr, then call
330 // std::terminate().
331 _GABIXX_NORETURN void __fatal_error(const char* message) _GABIXX_HIDDEN;
332 
333 }  // __gabixx
334 
335 #endif  // _GABIXX_CXXABI_DEFINES_H
336