2 * Copyright (c) 2018 Jaroslav Jindrak
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <__bits/abi.hpp>
35 void* __dso_handle
= nullptr;
48 destructor_t
* destructors
{nullptr};
49 std::size_t destructor_count
{0};
50 std::size_t destructor_size
{32};
53 * C atexit does not pass any arguments,
54 * but __cxa_finalize requires one so we
57 void atexit_destructors()
59 __cxa_finalize(nullptr);
64 * No need for a body, this function is called when a virtual
65 * call of a pure virtual function cannot be made.
67 extern "C" void __cxa_pure_virtual()
73 extern "C" int __aeabi_atexit(void* p
, void (*f
)(void*), void* d
)
75 return __cxa_atexit(f
, p
, d
);
79 extern "C" int __cxa_atexit(void (*f
)(void*), void* p
, void* d
)
81 if (!aux::destructors
)
83 aux::destructors
= new aux::destructor_t
[aux::destructor_size
];
84 std::atexit(aux::atexit_destructors
);
86 else if (aux::destructor_count
>= aux::destructor_size
)
88 auto tmp
= std::realloc(aux::destructors
, aux::destructor_size
* 2);
93 aux::destructors
= static_cast<aux::destructor_t
*>(tmp
);
94 aux::destructor_size
*= 2;
97 auto& destr
= aux::destructors
[aux::destructor_count
++];
105 extern "C" void __cxa_finalize(void *f
)
109 for (std::size_t i
= aux::destructor_count
; i
> 0; --i
)
111 if (aux::destructors
[i
- 1].func
)
112 (*aux::destructors
[i
- 1].func
)(aux::destructors
[i
- 1].ptr
);
117 for (std::size_t i
= aux::destructor_count
; i
> 0; --i
)
119 if (aux::destructors
[i
- 1].func
== f
)
121 (*aux::destructors
[i
- 1].func
)(aux::destructors
[i
- 1].ptr
);
122 aux::destructors
[i
- 1].func
= nullptr;
123 aux::destructors
[i
- 1].ptr
= nullptr;
124 aux::destructors
[i
- 1].dso
= nullptr;
125 // TODO: shift and decrement count
131 using guard_t
= std::uint64_t;
132 std::mutex static_guard_mtx
{};
134 extern "C" int __cxa_guard_acquire(guard_t
* guard
)
136 static_guard_mtx
.lock();
138 return !*((std::uint8_t*)guard
);
141 extern "C" void __cxa_guard_release(guard_t
* guard
)
143 *((std::uint8_t*)guard
) = 1;
145 static_guard_mtx
.unlock();
148 extern "C" void __cxa_guard_abort(guard_t
* guard
)
150 static_guard_mtx
.unlock();
153 __fundamental_type_info::~__fundamental_type_info()
156 __array_type_info::~__array_type_info()
159 __function_type_info::~__function_type_info()
162 __enum_type_info::~__enum_type_info()
165 __class_type_info::~__class_type_info()
168 __si_class_type_info::~__si_class_type_info()
171 __vmi_class_type_info::~__vmi_class_type_info()
174 __pbase_type_info::~__pbase_type_info()
177 __pointer_type_info::~__pointer_type_info()
180 __pointer_to_member_type_info::~__pointer_to_member_type_info()
184 * This structure represents part of the vtable segment
185 * that contains data related to dynamic_cast.
189 // Unimportant to us.
191 std::ptrdiff_t offset_to_top
;
192 std::type_info
* tinfo
;
196 extern "C" void* __dynamic_cast(const void* sub
, const __class_type_info
* src
,
197 const __class_type_info
* dst
, std::ptrdiff_t offset
)
200 // NOTE: as far as I understand it, we get vtable prefix from sub, get the type_info
201 // ptr from that and then climb the inheritance hierarchy upwards till we either
202 // fint dst or fail and return nullptr
207 extern "C" void __cxa_end_cleanup()