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
37namespace __cxxabiv1 {
38
39// Derived types of type_info below are based on 2.9.5 of C++ ABI.
40
41class __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.
50class __fundamental_type_info : public __shim_type_info
51{
52public:
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.
59class __array_type_info : public __shim_type_info
60{
61public:
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.
68class __function_type_info : public __shim_type_info
69{
70public:
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.
77class __enum_type_info : public __shim_type_info
78{
79public:
80  virtual ~__enum_type_info();
81  virtual bool can_catch(const __shim_type_info* thrown_type,
82                          void*& adjustedPtr) const;
83};
84
85
86class __class_type_info;
87
88// Used in __vmi_class_type_info
89struct __base_class_type_info
90{
91public:
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
102  bool is_virtual() const {
103    return (__offset_flags & __virtual_mask) != 0;
104  }
105
106  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)
112  long offset() const {
113    return __offset_flags >> __offset_shift;
114  }
115
116  long flags() const {
117    return __offset_flags & ((1 << __offset_shift) - 1);
118  }
119};
120
121// Helper struct to support catch-clause match
122struct __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.
139class __class_type_info : public __shim_type_info
140{
141public:
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
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
159protected:
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.
167class __si_class_type_info : public __class_type_info
168{
169public:
170  virtual ~__si_class_type_info();
171  const __class_type_info *__base_type;
172
173  virtual __class_type_info::class_type_info_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.
184class __vmi_class_type_info : public __class_type_info
185{
186public:
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
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
205class __pbase_type_info : public __shim_type_info
206{
207public:
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
227protected:
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
235private:
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
247class __pointer_type_info : public __pbase_type_info
248{
249public:
250  virtual ~__pointer_type_info();
251
252private:
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
259class __pointer_to_member_type_info : public __pbase_type_info
260{
261public:
262  __class_type_info* __context;
263
264  virtual ~__pointer_to_member_type_info();
265
266private:
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
273extern "C" {
274
275// Compatible with GNU C++
276const uint64_t __gxx_exception_class = 0x474E5543432B2B00LL; // GNUCC++\0
277
278struct __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
306struct __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
317namespace __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