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
83namespace __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
219namespace 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
228namespace __aeabiv1 {
229extern "C" {
230
231using __cxxabiv1::__cxa_vec_constructor;
232using __cxxabiv1::__cxa_vec_copy_constructor;
233using __cxxabiv1::__cxa_vec_destructor;
234
235void* __aeabi_vec_ctor_nocookie_nodtor(void* array_address,
236                                       __cxa_vec_constructor constructor,
237                                       size_t element_size,
238                                       size_t element_count);
239
240void* __aeabi_vec_ctor_cookie_nodtor(void* array_address,
241                                     __cxa_vec_constructor constructor,
242                                     size_t element_size,
243                                     size_t element_count);
244
245void* __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
252void* __aeabi_vec_new_nocookie_noctor(size_t element_size,
253                                      size_t element_count);
254
255void* __aeabi_vec_new_nocookie(size_t element_size,
256                               size_t element_count,
257                               __cxa_vec_constructor constructor);
258
259void* __aeabi_vec_new_cookie_nodtor(size_t element_size,
260                                    size_t element_count,
261                                    __cxa_vec_constructor constructor);
262
263void* __aeabi_vec_new_cookie(size_t element_size,
264                             size_t element_count,
265                             __cxa_vec_constructor constructor,
266                             __cxa_vec_destructor destructor);
267
268void* __aeabi_vec_dtor(void* array_address,
269                       __cxa_vec_destructor destructor,
270                       size_t element_size,
271                       size_t element_count);
272
273void* __aeabi_vec_dtor_cookie(void* array_address,
274                              __cxa_vec_destructor destructor);
275
276void __aeabi_vec_delete(void* array_address,
277                        __cxa_vec_destructor destructor);
278
279void __aeabi_vec_delete3(void* array_address,
280                         __cxa_vec_destructor destructor,
281                         void (*dealloc)(void*, size_t));
282
283void __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