diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/head/stack_unwind.h | |
download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/head/stack_unwind.h')
-rw-r--r-- | usr/src/head/stack_unwind.h | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/usr/src/head/stack_unwind.h b/usr/src/head/stack_unwind.h new file mode 100644 index 0000000000..5f6fd71eb1 --- /dev/null +++ b/usr/src/head/stack_unwind.h @@ -0,0 +1,298 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Public interfaces for AMD64 Unwind routines + */ + +#ifndef _STACK_UNWIND_H +#define _STACK_UNWIND_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__amd64) /* none of this is valid except for AMD64 */ + +typedef enum { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +} _Unwind_Reason_Code; + +typedef int _Unwind_Action; +extern const _Unwind_Action _UA_SEARCH_PHASE; +extern const _Unwind_Action _UA_CLEANUP_PHASE; +extern const _Unwind_Action _UA_HANDLER_FRAME; +extern const _Unwind_Action _UA_FORCE_UNWIND; + +struct _Unwind_Exception; +struct _Unwind_Context; + + +/* + * Signature of language specific call back for deleting exception object + */ +typedef void (*_Unwind_Exception_Cleanup_Fn)( + _Unwind_Reason_Code reason, + struct _Unwind_Exception *exc); + +/* + * Header preceding language specific exception object + * For Sun C++ these fields are the beginning of the + * language specific structure. + */ +struct _Unwind_Exception { + uint64_t exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + uint64_t private_1; + uint64_t private_2; +}; + +/* + * Signature for language specific routine - address is in eh_frame CIE. + * During phase one it predicts whether exception would be caught at this + * frame and during phase two selects a handler as predicted. An action + * of _UA_FORCE_UNWIND will prevent any catch block from being selected. + * + * The personality function is the only call back used when + * _Unwind_RaiseException() is called. + */ +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( + int version, + _Unwind_Action actions, + uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context); + +/* + * Signature of callback function that is used when _Unwind_ForcedUnwind() + * is called. It is called at every step of walkback and that can control + * the execution of the personality routine at each frame. + */ +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)( + int version, + _Unwind_Action actions, + uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context, + void *stop_parameter); + +/* + * Here begins the external functional interface + */ + +/* + * Used to implement C++ throw - starts walkback with caller's caller. + * The routine in the middle must use %rbp as a frame pointer + */ +_Unwind_Reason_Code _Unwind_RaiseException( + struct _Unwind_Exception *exception_object); + +/* + * Used (with different stop functions) for POSIX thread cancellation + * and stack walking - starts walkback with caller's caller. + * + * Note: must be called by a routine which has a real FP and doesn't use + * callee saves registers. + */ +_Unwind_Reason_Code _Unwind_ForcedUnwind( + struct _Unwind_Exception *exception_object, + _Unwind_Stop_Fn stop, + void *stop_parameter); + +/* + * Used to resume unwinding at end of cleanup (not catch) code + * Assumes that caller is language specific cleanup code and + * pops the stack one level before resuming walk. + */ +void _Unwind_Resume(struct _Unwind_Exception *exception_object); + +/* + * Calls destructor function for exception object + */ +void _Unwind_DeleteException(struct _Unwind_Exception *exception_object); +/* + * { + * (*(exception_object->exception_cleanup))(_URC_NO_REASON, + * exception_object); + * } + */ + + +#if 0 + +extern "C" _Unwind_Reason_Code +__example_stop_fn(int version, int actions, uint64_t exclass, + struct _Unwind_Exception *exception_object, + struct _Unwind_Context *ctx, void *_Sa) +{ + _Unwind_Reason_Code res; + + uint64_t fp = _Unwind_GetCFA(ctx); + + if (fp == 0 || _Unwind_GetGR(ctx, RET_ADD) == 0) { + if (no_return) + die; + res = _URC_END_OF_STACK; + } else { + /* + * Your logic here: + * res = ........ + */ + } + switch (res) { + case _URC_NO_REASON: + /* + * framework will call personality routine for current context + * then then move one frame back the stack and call here with + * updated context. POSIX thread cancellation uses this pattern. + * + * If this path is taken the exception object passed must have + * been constructed by the same language system supplying the + * personality routines. i.e. foreign exceptions are not + * implemented. + * + * The Sun Microsystems C++ runtime contains the routine + * + * _ex_unwind(_Unwind_Stop_fn sfunc, void *sfunc_arg) + * + * which is a wrapper around _Unwind_ForcedUnwind that + * sets up a C++ exception object. + * + * Once this path is taken, the stack frame from which + * _Unwind_ForcedUnwind was called is not guaranteed to + * still exist. Thus the return codes listed below which + * result in that call returning are rendered bogus. + * + * A thread reaching the end of the stack during cancellation + * must die instead of returning _URC_END_OF_STACK. + */ + break; + case _URC_CONTINUE_UNWIND: + /* + * framework will move one frame back the stack and + * call here with updated context + * + * The exception record supplied to _Unwind_ForcedUnwind + * need only contain the header and may be stack allocated + * if this function will never allow the personality + * function to run (as in a trace generator). + */ + break; + case _URC_INSTALL_CONTEXT: + /* + * framework will resume execution of user code at location + * specified by (altered) context + */ + _Unwind_Delete_Exception(res, exception_object); + break; + case _URC_NORMAL_STOP: + /* + * call to _Unwind_ForcedUnwind will return _URC_NORMAL_STOP + */ + _Unwind_Delete_Exception(res, exception_object); + break; + case _URC_END_OF_STACK: + /* + * call to _Unwind_ForcedUnwind will return _URC_END_OF_STACK + */ + _Unwind_Delete_Exception(res, exception_object); + break; + case _URC_FOREIGN_EXCEPTION_CAUGHT: + case _URC_FATAL_PHASE2_ERROR: + case _URC_FATAL_PHASE1_ERROR: + case _URC_HANDLER_FOUND: + /* + * call to _Unwind_ForcedUnwind will return + * _URC_FATAL_PHASE2_ERROR + */ + _Unwind_Delete_Exception(res, exception_object); + break; + } + return (res); +} + +#endif + +/* + * Stack frame context accessors defined in ABI + * (despite all the dire text in the ABI these are reliable Get/Set routines) + * Note: RA is handled as a GR value + */ + +/* + * Valid Index values for _Unwind_GetGR + */ +#define GPR_RBX 3 /* callee saves */ +#define FP_RBP 6 /* callee saves (optional frame pointer) */ +#define SP_RSP 7 /* callee saves */ +#define EIR_R12 12 /* callee saves */ +#define EIR_R13 13 /* callee saves */ +#define EIR_R14 14 /* callee saves */ +#define EIR_R15 15 /* callee saves */ +#define RET_ADD 16 /* virtual register - really caller's PC */ + +/* + * Valid Index values for _Unwind_SetGR + */ +#define GPR_RDX 1 /* landing pad parameter */ +#define GPR_RCX 2 /* landing pad parameter */ +#define GPR_RSI 4 /* landing pad parameter */ +#define GPR_RDI 5 /* landing pad parameter */ + +uint64_t _Unwind_GetGR(struct _Unwind_Context *context, int index); + +void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uint64_t new_value); + +uint64_t _Unwind_GetCFA(struct _Unwind_Context *context); + +uint64_t _Unwind_GetIP(struct _Unwind_Context *context); + +void _Unwind_SetIP(struct _Unwind_Context *context, uint64_t new_value); + +void *_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context); + +uint64_t _Unwind_GetRegionStart(struct _Unwind_Context *context); + +#endif /* __amd64 */ + +#ifdef __cplusplus +} +#endif + +#endif /* _STACK_UNWIND_H */ |