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 // The specifications for the declarations found in this header are
33 // the following:
34 //
35 // - Itanium C++ ABI [1]
36 //   Used on about every CPU architecture, _except_ ARM, this
37 //   is also commonly referred as the "generic C++ ABI".
38 //
39 //   NOTE: This document seems to only covers C++98
40 //
41 // - Itanium C++ ABI: Exception Handling. [2]
42 //   Supplement to the above document describing how exception
43 //   handle works with the generic C++ ABI. Again, this only
44 //   seems to support C++98.
45 //
46 // - C++ ABI for the ARM architecture [3]
47 //   Describes the ARM C++ ABI, mainly as a set of differences from
48 //   the generic one.
49 //
50 // - Exception Handling for the ARM Architecture [4]
51 //   Describes exception handling for ARM in detail. There are rather
52 //   important differences in the stack unwinding process and
53 //   exception cleanup.
54 //
55 // There are also no freely availabel documentation about certain
56 // features introduced in C++0x or later. In this case, the best
57 // source for information are the GNU and LLVM C++ runtime libraries
58 // (libcxxabi, libsupc++ and even libc++ sources), as well as a few
59 // proposals, for example:
60 //
61 // - For exception propagation:
62 //   http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2179.html
63 //   But the paper only describs the high-level language feature, not
64 //   the low-level runtime support required to implement it.
65 //
66 // - For nested exceptions:
67 //   http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2559.html
68 //   Yet another high-level description without low-level details.
69 //
70 #include <gabixx_config.h>
71 
72 #include <exception>
73 #include <stdint.h>
74 #include <typeinfo>
75 #include <unwind.h>
76 
77 // When LIBCXXABI, gabi++ should emulate libc++abi. _LIBCPPABI_VERSION must
78 // be defined in cxxabi.h to complete this abstraction for libc++.
79 #if defined(LIBCXXABI)
80 #define _LIBCPPABI_VERSION 1001
81 #endif
82 
83 namespace __cxxabiv1
84 {
85   extern "C" {
86 
87     // TODO: Support dependent exception
88     // TODO: Support C++0x exception propagation
89     // http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
90     struct __cxa_exception;
91     struct __cxa_eh_globals;
92 
93     __cxa_eh_globals* __cxa_get_globals() _GABIXX_NOEXCEPT ;
94     __cxa_eh_globals* __cxa_get_globals_fast() _GABIXX_NOEXCEPT;
95 
96     void* __cxa_allocate_exception(size_t thrown_size) _GABIXX_NOEXCEPT;
97     void __cxa_free_exception(void* thrown_exception) _GABIXX_NOEXCEPT;
98 
99     void __cxa_throw(void* thrown_exception,
100                      std::type_info* tinfo,
101                      void (*dest)(void*)) _GABIXX_NORETURN;
102 
103     void __cxa_rethrow() _GABIXX_NORETURN;
104 
105     void* __cxa_begin_catch(void* exceptionObject) _GABIXX_NOEXCEPT;
106     void __cxa_end_catch() _GABIXX_NOEXCEPT;
107 
108 #ifdef __arm__
109     bool __cxa_begin_cleanup(_Unwind_Exception*);
110     void __cxa_end_cleanup();
111 #endif
112 
113     void __cxa_bad_cast() _GABIXX_NORETURN;
114     void __cxa_bad_typeid() _GABIXX_NORETURN;
115 
116     void* __cxa_get_exception_ptr(void* exceptionObject) _GABIXX_NOEXCEPT;
117 
118     void __cxa_pure_virtual() _GABIXX_NORETURN;
119     void __cxa_deleted_virtual() _GABIXX_NORETURN;
120 
121     // Missing libcxxabi functions.
122     bool __cxa_uncaught_exception() _GABIXX_NOEXCEPT;
123 
124     void __cxa_decrement_exception_refcount(void* exceptionObject)
125         _GABIXX_NOEXCEPT;
126 
127     void __cxa_increment_exception_refcount(void* exceptionObject)
128         _GABIXX_NOEXCEPT;
129 
130     void __cxa_rethrow_primary_exception(void* exceptionObject);
131 
132     void* __cxa_current_primary_exception() _GABIXX_NOEXCEPT;
133 
134     // The ARM ABI mandates that constructors and destructors
135     // must return 'this', i.e. their first parameter. This is
136     // also true for __cxa_vec_ctor and __cxa_vec_cctor.
137 #ifdef __arm__
138     typedef void* __cxa_vec_ctor_return_type;
139 #else
140     typedef void __cxa_vec_ctor_return_type;
141 #endif
142 
143     typedef __cxa_vec_ctor_return_type
144         (*__cxa_vec_constructor)(void *);
145 
146     typedef __cxa_vec_constructor __cxa_vec_destructor;
147 
148     typedef __cxa_vec_ctor_return_type
149         (*__cxa_vec_copy_constructor)(void*, void*);
150 
151     void* __cxa_vec_new(size_t element_count,
152                         size_t element_size,
153                         size_t padding_size,
154                         __cxa_vec_constructor constructor,
155                         __cxa_vec_destructor destructor);
156 
157     void* __cxa_vec_new2(size_t element_count,
158                          size_t element_size,
159                          size_t padding_size,
160                          __cxa_vec_constructor constructor,
161                          __cxa_vec_destructor destructor,
162                          void* (*alloc)(size_t),
163                          void  (*dealloc)(void*));
164 
165     void* __cxa_vec_new3(size_t element_count,
166                          size_t element_size,
167                          size_t padding_size,
168                          __cxa_vec_constructor constructor,
169                          __cxa_vec_destructor destructor,
170                          void* (*alloc)(size_t),
171                          void  (*dealloc)(void*, size_t));
172 
173     __cxa_vec_ctor_return_type
174     __cxa_vec_ctor(void*  array_address,
175                    size_t element_count,
176                    size_t element_size,
177                    __cxa_vec_constructor constructor,
178                    __cxa_vec_destructor destructor);
179 
180     void __cxa_vec_dtor(void*  array_address,
181                         size_t element_count,
182                         size_t element_size,
183                         __cxa_vec_destructor destructor);
184 
185     void __cxa_vec_cleanup(void* array_address,
186                            size_t element_count,
187                            size_t element_size,
188                            __cxa_vec_destructor destructor);
189 
190     void __cxa_vec_delete(void*  array_address,
191                           size_t element_size,
192                           size_t padding_size,
193                           __cxa_vec_destructor destructor);
194 
195     void __cxa_vec_delete2(void* array_address,
196                            size_t element_size,
197                            size_t padding_size,
198                            __cxa_vec_destructor destructor,
199                            void  (*dealloc)(void*));
200 
201     void __cxa_vec_delete3(void* array_address,
202                            size_t element_size,
203                            size_t padding_size,
204                            __cxa_vec_destructor destructor,
205                            void  (*dealloc) (void*, size_t));
206 
207     __cxa_vec_ctor_return_type
208     __cxa_vec_cctor(void*  dest_array,
209                     void*  src_array,
210                     size_t element_count,
211                     size_t element_size,
212                     __cxa_vec_copy_constructor constructor,
213                     __cxa_vec_destructor destructor );
214 
215   } // extern "C"
216 
217 } // namespace __cxxabiv1
218 
219 namespace abi = __cxxabiv1;
220 
221 #if _GABIXX_ARM_ABI
222 // ARM-specific ABI additions. They  must be provided by the
223 // C++ runtime to simplify calling code generated by the compiler.
224 // Note that neither GCC nor Clang seem to use these, but this can
225 // happen when using machine code generated with other ocmpilers
226 // like RCVT.
227 
228 namespace __aeabiv1 {
229 extern "C" {
230 
231 using __cxxabiv1::__cxa_vec_constructor;
232 using __cxxabiv1::__cxa_vec_copy_constructor;
233 using __cxxabiv1::__cxa_vec_destructor;
234 
235 void* __aeabi_vec_ctor_nocookie_nodtor(void* array_address,
236                                        __cxa_vec_constructor constructor,
237                                        size_t element_size,
238                                        size_t element_count);
239 
240 void* __aeabi_vec_ctor_cookie_nodtor(void* array_address,
241                                      __cxa_vec_constructor constructor,
242                                      size_t element_size,
243                                      size_t element_count);
244 
245 void* __aeabi_vec_cctor_nocookie_nodtor(
246     void* dst_array,
247     void* src_array,
248     size_t element_size,
249     size_t element_count,
250     __cxa_vec_copy_constructor constructor);
251 
252 void* __aeabi_vec_new_nocookie_noctor(size_t element_size,
253                                       size_t element_count);
254 
255 void* __aeabi_vec_new_nocookie(size_t element_size,
256                                size_t element_count,
257                                __cxa_vec_constructor constructor);
258 
259 void* __aeabi_vec_new_cookie_nodtor(size_t element_size,
260                                     size_t element_count,
261                                     __cxa_vec_constructor constructor);
262 
263 void* __aeabi_vec_new_cookie(size_t element_size,
264                              size_t element_count,
265                              __cxa_vec_constructor constructor,
266                              __cxa_vec_destructor destructor);
267 
268 void* __aeabi_vec_dtor(void* array_address,
269                        __cxa_vec_destructor destructor,
270                        size_t element_size,
271                        size_t element_count);
272 
273 void* __aeabi_vec_dtor_cookie(void* array_address,
274                               __cxa_vec_destructor destructor);
275 
276 void __aeabi_vec_delete(void* array_address,
277                         __cxa_vec_destructor destructor);
278 
279 void __aeabi_vec_delete3(void* array_address,
280                          __cxa_vec_destructor destructor,
281                          void (*dealloc)(void*, size_t));
282 
283 void __aeabi_vec_delete3_nodtor(void* array_address,
284                                 void (*dealloc)(void*, size_t));
285 
286 }  // extern "C"
287 }  // namespace __
288 
289 #endif  // _GABIXX_ARM_ABI == 1
290 
291 #endif /* defined(__GABIXX_CXXABI_H__) */
292 
293