• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2011 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 
29 #ifndef __GABIXX_CXXABI_H__
30 #define __GABIXX_CXXABI_H__
31 
32 #include <exception>
33 #include <typeinfo>
34 #include <unwind.h>
35 
36 namespace __cxxabiv1
37 {
38   // Derived types of type_info below are based on 2.9.5 of C++ ABI.
39 
40   class __shim_type_info : public std::type_info
41   {
42    public:
43     virtual ~__shim_type_info();
44     virtual bool can_catch(const __shim_type_info* thrown_type,
45                            void*& adjustedPtr) const = 0;
46   };
47 
48   // Typeinfo for fundamental types.
49   class __fundamental_type_info : public __shim_type_info
50   {
51   public:
52     virtual ~__fundamental_type_info();
53     virtual bool can_catch(const __shim_type_info* thrown_type,
54                            void*& adjustedPtr) const;
55   };
56 
57   // Typeinfo for array types.
58   class __array_type_info : public __shim_type_info
59   {
60   public:
61     virtual ~__array_type_info();
62     virtual bool can_catch(const __shim_type_info* thrown_type,
63                            void*& adjustedPtr) const;
64   };
65 
66   // Typeinfo for function types.
67   class __function_type_info : public __shim_type_info
68   {
69   public:
70     virtual ~__function_type_info();
71     virtual bool can_catch(const __shim_type_info* thrown_type,
72                            void*& adjustedPtr) const;
73   };
74 
75   // Typeinfo for enum types.
76   class __enum_type_info : public __shim_type_info
77   {
78   public:
79     virtual ~__enum_type_info();
80     virtual bool can_catch(const __shim_type_info* thrown_type,
81                            void*& adjustedPtr) const;
82   };
83 
84 
85   class __class_type_info;
86 
87   // Used in __vmi_class_type_info
88   struct __base_class_type_info
89   {
90   public:
91     const __class_type_info *__base_type;
92 
93     long __offset_flags;
94 
95     enum __offset_flags_masks {
96       __virtual_mask = 0x1,
97       __public_mask = 0x2,
98       __offset_shift = 8   // lower 8 bits are flags
99     };
100 
is_virtual__base_class_type_info101     bool is_virtual() const {
102       return (__offset_flags & __virtual_mask) != 0;
103     }
104 
is_public__base_class_type_info105     bool is_public() const {
106       return (__offset_flags & __public_mask) != 0;
107     }
108 
109     // FIXME: Right-shift of signed integer is implementation dependent.
110     // GCC Implement is as signed (as we expect)
offset__base_class_type_info111     long offset() const {
112       return __offset_flags >> __offset_shift;
113     }
114 
flags__base_class_type_info115     long flags() const {
116       return __offset_flags & ((1 << __offset_shift) - 1);
117     }
118   };
119 
120   // Helper struct to support catch-clause match
121   struct __UpcastInfo {
122     enum ContainedStatus {
123       unknown = 0,
124       has_public_contained,
125       has_ambig_or_not_public
126     };
127 
128     ContainedStatus status;
129     const __class_type_info* base_type;
130     void* adjustedPtr;
131     unsigned int premier_flags;
132     bool nullobj_may_conflict;
133 
134     __UpcastInfo(const __class_type_info* type);
135   };
136 
137   // Typeinfo for classes with no bases.
138   class __class_type_info : public __shim_type_info
139   {
140   public:
141     virtual ~__class_type_info();
142     virtual bool can_catch(const __shim_type_info* thrown_type,
143                            void*& adjustedPtr) const;
144 
145     enum class_type_info_code {
146       CLASS_TYPE_INFO_CODE,
147       SI_CLASS_TYPE_INFO_CODE,
148       VMI_CLASS_TYPE_INFO_CODE
149     };
150 
151     virtual class_type_info_code
code()152       code() const { return CLASS_TYPE_INFO_CODE; }
153 
154     virtual bool walk_to(const __class_type_info* base_type,
155                          void*& adjustedPtr,
156                          __UpcastInfo& info) const;
157 
158   protected:
159     bool self_class_type_match(const __class_type_info* base_type,
160                                void*& adjustedPtr,
161                                __UpcastInfo& info) const;
162   };
163 
164   // Typeinfo for classes containing only a single, public, non-virtual base at
165   // offset zero.
166   class __si_class_type_info : public __class_type_info
167   {
168   public:
169     virtual ~__si_class_type_info();
170     const __class_type_info *__base_type;
171 
172     virtual __class_type_info::class_type_info_code
code()173       code() const { return SI_CLASS_TYPE_INFO_CODE; }
174 
175     virtual bool walk_to(const __class_type_info* base_type,
176                          void*& adjustedPtr,
177                          __UpcastInfo& info) const;
178   };
179 
180 
181   // Typeinfo for classes with bases that do not satisfy the
182   // __si_class_type_info constraints.
183   class __vmi_class_type_info : public __class_type_info
184   {
185   public:
186     virtual ~__vmi_class_type_info();
187     unsigned int __flags;
188     unsigned int __base_count;
189     __base_class_type_info __base_info[1];
190 
191     enum __flags_masks {
192       __non_diamond_repeat_mask = 0x1,
193       __diamond_shaped_mask = 0x2,
194     };
195 
196     virtual __class_type_info::class_type_info_code
code()197       code() const { return VMI_CLASS_TYPE_INFO_CODE; }
198 
199     virtual bool walk_to(const __class_type_info* base_type,
200                          void*& adjustedPtr,
201                          __UpcastInfo& info) const;
202   };
203 
204   class __pbase_type_info : public __shim_type_info
205   {
206   public:
207     virtual ~__pbase_type_info();
208     virtual bool can_catch(const __shim_type_info* thrown_type,
209                            void*& adjustedPtr) const;
210     unsigned int __flags;
211     const __shim_type_info* __pointee;
212 
213     enum __masks {
214       __const_mask = 0x1,
215       __volatile_mask = 0x2,
216       __restrict_mask = 0x4,
217       __incomplete_mask = 0x8,
218       __incomplete_class_mask = 0x10
219     };
220 
221 
222     virtual bool can_catch_typeinfo_wrapper(const __shim_type_info* thrown_type,
223                                             void*& adjustedPtr,
224                                             unsigned tracker) const;
225 
226   protected:
227     enum __constness_tracker_status {
228       first_time_init = 0x1,
229       keep_constness = 0x2,
230       after_gap = 0x4         // after one non-const qualified,
231                               // we cannot face const again in future
232     };
233 
234   private:
235     bool can_catch_ptr(const __pbase_type_info *thrown_type,
236                        void *&adjustedPtr,
237                        unsigned tracker) const;
238 
239     // Return true if making decision done.
240     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
241                                   void*& adjustedPtr,
242                                   unsigned tracker,
243                                   bool& result) const = 0;
244   };
245 
246   class __pointer_type_info : public __pbase_type_info
247   {
248   public:
249     virtual ~__pointer_type_info();
250 
251   private:
252     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
253                                   void*& adjustedPtr,
254                                   unsigned tracker,
255                                   bool& result) const;
256   };
257 
258   class __pointer_to_member_type_info : public __pbase_type_info
259   {
260   public:
261     __class_type_info* __context;
262 
263     virtual ~__pointer_to_member_type_info();
264 
265   private:
266     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
267                                   void*& adjustedPtr,
268                                   unsigned tracker,
269                                   bool& result) const;
270   };
271 
272 
273   extern "C" {
274 
275     // Compatible with GNU C++
276     const uint64_t __gxx_exception_class = 0x474E5543432B2B00LL; // GNUCC++\0
277 
278     // TODO: Support dependent exception
279     // TODO: Support C++0x exception propagation
280     // http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
281     struct __cxa_exception {
282       size_t referenceCount;
283 
284       std::type_info* exceptionType;
285       void (*exceptionDestructor)(void*);
286       std::unexpected_handler unexpectedHandler;
287       std::terminate_handler terminateHandler;
288       __cxa_exception* nextException;
289 
290       int handlerCount;
291 #ifdef __arm__
292       /**
293        * ARM EHABI requires the unwind library to keep track of exceptions
294        * during cleanups.  These support nesting, so we need to keep a list of
295        * them.
296        */
297       __cxa_exception* nextCleanup;
298       int cleanupCount;
299 #endif
300       int handlerSwitchValue;
301       const uint8_t* actionRecord;
302       const uint8_t* languageSpecificData;
303       void* catchTemp;
304       void* adjustedPtr;
305 
306       _Unwind_Exception unwindHeader; // must be last
307     };
308 
309     struct __cxa_eh_globals {
310       __cxa_exception* caughtExceptions;
311       unsigned int uncaughtExceptions;
312 #ifdef __arm__
313       __cxa_exception* cleanupExceptions;
314 #endif
315     };
316 
317     struct __cxa_thread_info {
318       std::unexpected_handler unexpectedHandler;
319       std::terminate_handler terminateHandler;
320       _Unwind_Exception* currentCleanup;
321 
322       __cxa_eh_globals globals;
323     };
324 
325     __cxa_eh_globals* __cxa_get_globals();
326     __cxa_eh_globals* __cxa_get_globals_fast();
327 
328     void* __cxa_allocate_exception(size_t thrown_size);
329     void __cxa_free_exception(void* thrown_exception);
330 
331     void __cxa_throw(void* thrown_exception, std::type_info* tinfo, void (*dest)(void*));
332     void __cxa_rethrow();
333 
334     void* __cxa_begin_catch(void* exceptionObject);
335     void __cxa_end_catch();
336 
337     bool __cxa_begin_cleanup(_Unwind_Exception*);
338     void __cxa_end_cleanup();
339 
340     void __cxa_bad_cast();
341     void __cxa_bad_typeid();
342 
343     void* __cxa_get_exception_ptr(void* exceptionObject);
344 
345     void __cxa_pure_virtual();
346 
347     // Missing libcxxabi functions.
348     bool __cxa_uncaught_exception() throw();
349     void __cxa_decrement_exception_refcount(void* exceptionObject) throw();
350     void __cxa_increment_exception_refcount(void* exceptionObject) throw();
351     void __cxa_rethrow_primary_exception(void* exceptionObject);
352     void* __cxa_current_primary_exception() throw();
353 
354   } // extern "C"
355 
356 } // namespace __cxxabiv1
357 
358 namespace abi = __cxxabiv1;
359 
360 #endif /* defined(__GABIXX_CXXABI_H__) */
361 
362