ia64_cxx_abi.h
Go to the documentation of this file.
1 //
2 // Bareflank Unwind Library
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 #ifndef IA64_CXX_ABI_H
23 #define IA64_CXX_ABI_H
24 
25 #include <stdint.h>
26 
27 struct _Unwind_Exception;
28 
29 // -----------------------------------------------------------------------------
30 // Overview
31 // -----------------------------------------------------------------------------
32 //
33 // The IA64 C++ ABI specification describes a set of functions that are used
34 // to perform stack unwinding for exception support. This implementation uses
35 // the following documentation:
36 //
37 // http://mentorembedded.github.io/cxx-abi/abi-eh.html#cxx-abi
38 //
39 // Also note that this information can also be found in the System V 64bit
40 // ABI specification:
41 //
42 // http://www.x86-64.org/documentation/abi.pdf
43 //
44 
45 // -----------------------------------------------------------------------------
46 // 1.1 Exception Handler Framework
47 // -----------------------------------------------------------------------------
48 
49 // The exception framework can be broken up into three layers:
50 //
51 // - Layer 3: Defines the language specific keywords for exception support.
52 // In C++, this is the "throw" and "catch" keywords that the programmer
53 // is actually using.
54 //
55 // - Layer 2: The compiler, using the layer 3 keywords, will automatically
56 // generate calls to layer 2 functions. These functions are provided by the
57 // ABI (for GCC this is libsupc++, and for LLVM, this is libcxxabi). These
58 // functions include __cxa_throw, __cxa_catch_begin, etc... These ABIs also
59 // provide the "personality" function that is used to determine which catch
60 // blocks we should stop unwinding to.
61 //
62 // - Layer 3: This layer defines the actual unwinding code. Layer two is an ABI
63 // specific abstraction layer, but layer 3 is actually performing the
64 // unwinding. This layer is usually provided by the compiler, as it is
65 // architecture specific. The problem with most implementations is, they
66 // require user space code to work. This one does not. The code defined here
67 // belongs to this layer
68 
69 // -----------------------------------------------------------------------------
70 // 1.2 Data Structures
71 // -----------------------------------------------------------------------------
72 
87 typedef enum
88 {
98 
100 
124  _Unwind_Reason_Code reason,
125  _Unwind_Exception *exc);
126 
160 {
161  uint64_t exception_class;
163  uint64_t private_1;
164  uint64_t private_2;
165 };
166 
170 struct _Unwind_Context;
171 
172 // -----------------------------------------------------------------------------
173 // 1.3 Throwing an Exception
174 // -----------------------------------------------------------------------------
175 //
176 // Throwing an exception can be done with two different functions:
177 // - _Unwind_RaiseException
178 // - _Unwind_Resume
179 //
180 // These functions are basically identical. They both get the current register
181 // state, and then unwind the stack until the personality function says to stop.
182 // The difference is, _Unwind_RaiseException is executed in two phases, a
183 // search phase and a cleanup phase, while _Unwind_Resume only performs the
184 // cleanup phase.
185 //
186 // It should be noted that if code contains RAII and has to preform cleanup,
187 // it's likely the _Unwind_RaiseException will be told to jump into the code,
188 // as if the "catch" block was identified, even though it wasn't the compiler
189 // will throw again by calling _Unwind_Resume. This code really doesn't
190 // know the difference between a real "throw, rethrow, catch" and a "throw,
191 // cleanup, catch" as they look identical
192 //
193 
194 extern "C" _Unwind_Reason_Code
195 _Unwind_RaiseException(_Unwind_Exception *exception_object);
196 
197 extern "C" void
198 _Unwind_Resume(_Unwind_Exception *exception_object);
199 
200 // -----------------------------------------------------------------------------
201 // 1.4 Exception Object Management
202 // -----------------------------------------------------------------------------
203 //
204 // The exception object is created by layer 2, and contains more information
205 // than what is visible in layer 3, so layer 2 has to provide the delete
206 // function, which is located in the exception object itself.
207 //
208 
209 extern "C" void
210 _Unwind_DeleteException(_Unwind_Exception *exception_object);
211 
212 // -----------------------------------------------------------------------------
213 // 1.5 Context Management
214 // -----------------------------------------------------------------------------
215 //
216 // These functions are basically just wrappers around the functionality that
217 // we store in the context. For example, layer 2 needs to be able to to set
218 // and get registers (both general purpose registers as well as the
219 // instruction pointer). Layer 2, which has the personality function, will also
220 // need to know where the LSDA is, so that it can use this information to
221 // find each catch block (view the LSDA as nothing more than a giant list
222 // of C++ typeinfo blocks, that can be used in giant switch statement). Layer
223 // 2 also need to know where the start of the FDE is (i.e. pc_begin)
224 //
225 
226 extern "C" uintptr_t
227 _Unwind_GetGR(_Unwind_Context *context, int index);
228 
229 extern "C" void
230 _Unwind_SetGR(_Unwind_Context *context, int index, uintptr_t value);
231 
232 extern "C" uintptr_t
233 _Unwind_GetIP(_Unwind_Context *context);
234 
235 extern "C" void
236 _Unwind_SetIP(_Unwind_Context *context, uintptr_t value);
237 
238 extern "C" uintptr_t
239 _Unwind_GetLanguageSpecificData(_Unwind_Context *context);
240 
241 extern "C" uintptr_t
242 _Unwind_GetRegionStart(_Unwind_Context *context);
243 
244 // -----------------------------------------------------------------------------
245 // 1.6 Personality Routine
246 // -----------------------------------------------------------------------------
247 //
248 // The personality routine is called by this code, and it tells us when to stop
249 // looking for a catch block. It uses information in the LSDA to determine if
250 // a catch block is in the current CFA. Layer 3 has to search in two phases.
251 // The first phase tells the personality function just to tell us when to stop.
252 // The second phase does the actual cleanup and then stops. Note that if a
253 // custom personality function was created, you could reduce this to a single
254 // cleanup phase, as the initial search phase is a not needed in most cases.
255 //
256 // Also note that since this is only meant to be used by C++, we don't need
257 // the force unwind functionality
258 //
259 
260 typedef int _Unwind_Action;
261 static const _Unwind_Action _UA_SEARCH_PHASE = 1;
262 static const _Unwind_Action _UA_CLEANUP_PHASE = 2;
263 static const _Unwind_Action _UA_HANDLER_FRAME = 4;
264 static const _Unwind_Action _UA_FORCE_UNWIND = 8;
265 
267  _Unwind_Action actions, uint64_t exceptionClass,
268  _Unwind_Exception *exceptionObject,
269  _Unwind_Context *context);
270 
271 // -----------------------------------------------------------------------------
272 // GNU Extensions
273 // -----------------------------------------------------------------------------
274 //
275 // GCC adds some additional functions that are only needed by the unit test,
276 // as LLVM doesn't add any additional functionality.
277 //
278 
279 extern "C" uintptr_t
280 _Unwind_GetIPInfo(_Unwind_Context *context, int *ip_before_insn);
281 
282 #endif
void(* _Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code reason, _Unwind_Exception *exc)
Definition: ia64_cxx_abi.h:123
_Unwind_Exception_Cleanup_Fn exception_cleanup
Definition: ia64_cxx_abi.h:162
uintptr_t _Unwind_GetIPInfo(_Unwind_Context *context, int *ip_before_insn)
uint64_t exception_class
Definition: ia64_cxx_abi.h:161
auto index(const T virt, const F from)
void _Unwind_SetIP(_Unwind_Context *context, uintptr_t value)
void _Unwind_SetGR(_Unwind_Context *context, int index, uintptr_t value)
uintptr_t _Unwind_GetGR(_Unwind_Context *context, int index)
uintptr_t _Unwind_GetIP(_Unwind_Context *context)
uintptr_t _Unwind_GetRegionStart(_Unwind_Context *context)
_Unwind_Reason_Code
Definition: ia64_cxx_abi.h:87
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object)
void _Unwind_DeleteException(_Unwind_Exception *exception_object)
_Unwind_Reason_Code(* __personality_routine)(int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception *exceptionObject, _Unwind_Context *context)
Definition: ia64_cxx_abi.h:266
int _Unwind_Action
Definition: ia64_cxx_abi.h:260
uintptr_t _Unwind_GetLanguageSpecificData(_Unwind_Context *context)
void _Unwind_Resume(_Unwind_Exception *exception_object)