1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * Public interfaces for AMD64 Unwind routines 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #ifndef _STACK_UNWIND_H 32*7c478bd9Sstevel@tonic-gate #define _STACK_UNWIND_H 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 39*7c478bd9Sstevel@tonic-gate extern "C" { 40*7c478bd9Sstevel@tonic-gate #endif 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #if defined(__amd64) /* none of this is valid except for AMD64 */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate typedef enum { 45*7c478bd9Sstevel@tonic-gate _URC_NO_REASON = 0, 46*7c478bd9Sstevel@tonic-gate _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 47*7c478bd9Sstevel@tonic-gate _URC_FATAL_PHASE2_ERROR = 2, 48*7c478bd9Sstevel@tonic-gate _URC_FATAL_PHASE1_ERROR = 3, 49*7c478bd9Sstevel@tonic-gate _URC_NORMAL_STOP = 4, 50*7c478bd9Sstevel@tonic-gate _URC_END_OF_STACK = 5, 51*7c478bd9Sstevel@tonic-gate _URC_HANDLER_FOUND = 6, 52*7c478bd9Sstevel@tonic-gate _URC_INSTALL_CONTEXT = 7, 53*7c478bd9Sstevel@tonic-gate _URC_CONTINUE_UNWIND = 8 54*7c478bd9Sstevel@tonic-gate } _Unwind_Reason_Code; 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate typedef int _Unwind_Action; 57*7c478bd9Sstevel@tonic-gate extern const _Unwind_Action _UA_SEARCH_PHASE; 58*7c478bd9Sstevel@tonic-gate extern const _Unwind_Action _UA_CLEANUP_PHASE; 59*7c478bd9Sstevel@tonic-gate extern const _Unwind_Action _UA_HANDLER_FRAME; 60*7c478bd9Sstevel@tonic-gate extern const _Unwind_Action _UA_FORCE_UNWIND; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate struct _Unwind_Exception; 63*7c478bd9Sstevel@tonic-gate struct _Unwind_Context; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate /* 67*7c478bd9Sstevel@tonic-gate * Signature of language specific call back for deleting exception object 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate typedef void (*_Unwind_Exception_Cleanup_Fn)( 70*7c478bd9Sstevel@tonic-gate _Unwind_Reason_Code reason, 71*7c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exc); 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * Header preceding language specific exception object 75*7c478bd9Sstevel@tonic-gate * For Sun C++ these fields are the beginning of the 76*7c478bd9Sstevel@tonic-gate * language specific structure. 77*7c478bd9Sstevel@tonic-gate */ 78*7c478bd9Sstevel@tonic-gate struct _Unwind_Exception { 79*7c478bd9Sstevel@tonic-gate uint64_t exception_class; 80*7c478bd9Sstevel@tonic-gate _Unwind_Exception_Cleanup_Fn exception_cleanup; 81*7c478bd9Sstevel@tonic-gate uint64_t private_1; 82*7c478bd9Sstevel@tonic-gate uint64_t private_2; 83*7c478bd9Sstevel@tonic-gate }; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /* 86*7c478bd9Sstevel@tonic-gate * Signature for language specific routine - address is in eh_frame CIE. 87*7c478bd9Sstevel@tonic-gate * During phase one it predicts whether exception would be caught at this 88*7c478bd9Sstevel@tonic-gate * frame and during phase two selects a handler as predicted. An action 89*7c478bd9Sstevel@tonic-gate * of _UA_FORCE_UNWIND will prevent any catch block from being selected. 90*7c478bd9Sstevel@tonic-gate * 91*7c478bd9Sstevel@tonic-gate * The personality function is the only call back used when 92*7c478bd9Sstevel@tonic-gate * _Unwind_RaiseException() is called. 93*7c478bd9Sstevel@tonic-gate */ 94*7c478bd9Sstevel@tonic-gate typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( 95*7c478bd9Sstevel@tonic-gate int version, 96*7c478bd9Sstevel@tonic-gate _Unwind_Action actions, 97*7c478bd9Sstevel@tonic-gate uint64_t exceptionClass, 98*7c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exceptionObject, 99*7c478bd9Sstevel@tonic-gate struct _Unwind_Context *context); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate /* 102*7c478bd9Sstevel@tonic-gate * Signature of callback function that is used when _Unwind_ForcedUnwind() 103*7c478bd9Sstevel@tonic-gate * is called. It is called at every step of walkback and that can control 104*7c478bd9Sstevel@tonic-gate * the execution of the personality routine at each frame. 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)( 107*7c478bd9Sstevel@tonic-gate int version, 108*7c478bd9Sstevel@tonic-gate _Unwind_Action actions, 109*7c478bd9Sstevel@tonic-gate uint64_t exceptionClass, 110*7c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exceptionObject, 111*7c478bd9Sstevel@tonic-gate struct _Unwind_Context *context, 112*7c478bd9Sstevel@tonic-gate void *stop_parameter); 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* 115*7c478bd9Sstevel@tonic-gate * Here begins the external functional interface 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * Used to implement C++ throw - starts walkback with caller's caller. 120*7c478bd9Sstevel@tonic-gate * The routine in the middle must use %rbp as a frame pointer 121*7c478bd9Sstevel@tonic-gate */ 122*7c478bd9Sstevel@tonic-gate _Unwind_Reason_Code _Unwind_RaiseException( 123*7c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exception_object); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate /* 126*7c478bd9Sstevel@tonic-gate * Used (with different stop functions) for POSIX thread cancellation 127*7c478bd9Sstevel@tonic-gate * and stack walking - starts walkback with caller's caller. 128*7c478bd9Sstevel@tonic-gate * 129*7c478bd9Sstevel@tonic-gate * Note: must be called by a routine which has a real FP and doesn't use 130*7c478bd9Sstevel@tonic-gate * callee saves registers. 131*7c478bd9Sstevel@tonic-gate */ 132*7c478bd9Sstevel@tonic-gate _Unwind_Reason_Code _Unwind_ForcedUnwind( 133*7c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exception_object, 134*7c478bd9Sstevel@tonic-gate _Unwind_Stop_Fn stop, 135*7c478bd9Sstevel@tonic-gate void *stop_parameter); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* 138*7c478bd9Sstevel@tonic-gate * Used to resume unwinding at end of cleanup (not catch) code 139*7c478bd9Sstevel@tonic-gate * Assumes that caller is language specific cleanup code and 140*7c478bd9Sstevel@tonic-gate * pops the stack one level before resuming walk. 141*7c478bd9Sstevel@tonic-gate */ 142*7c478bd9Sstevel@tonic-gate void _Unwind_Resume(struct _Unwind_Exception *exception_object); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * Calls destructor function for exception object 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate void _Unwind_DeleteException(struct _Unwind_Exception *exception_object); 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * { 150*7c478bd9Sstevel@tonic-gate * (*(exception_object->exception_cleanup))(_URC_NO_REASON, 151*7c478bd9Sstevel@tonic-gate * exception_object); 152*7c478bd9Sstevel@tonic-gate * } 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate #if 0 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate extern "C" _Unwind_Reason_Code 159*7c478bd9Sstevel@tonic-gate __example_stop_fn(int version, int actions, uint64_t exclass, 160*7c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exception_object, 161*7c478bd9Sstevel@tonic-gate struct _Unwind_Context *ctx, void *_Sa) 162*7c478bd9Sstevel@tonic-gate { 163*7c478bd9Sstevel@tonic-gate _Unwind_Reason_Code res; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate uint64_t fp = _Unwind_GetCFA(ctx); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate if (fp == 0 || _Unwind_GetGR(ctx, RET_ADD) == 0) { 168*7c478bd9Sstevel@tonic-gate if (no_return) 169*7c478bd9Sstevel@tonic-gate die; 170*7c478bd9Sstevel@tonic-gate res = _URC_END_OF_STACK; 171*7c478bd9Sstevel@tonic-gate } else { 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * Your logic here: 174*7c478bd9Sstevel@tonic-gate * res = ........ 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate switch (res) { 178*7c478bd9Sstevel@tonic-gate case _URC_NO_REASON: 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * framework will call personality routine for current context 181*7c478bd9Sstevel@tonic-gate * then then move one frame back the stack and call here with 182*7c478bd9Sstevel@tonic-gate * updated context. POSIX thread cancellation uses this pattern. 183*7c478bd9Sstevel@tonic-gate * 184*7c478bd9Sstevel@tonic-gate * If this path is taken the exception object passed must have 185*7c478bd9Sstevel@tonic-gate * been constructed by the same language system supplying the 186*7c478bd9Sstevel@tonic-gate * personality routines. i.e. foreign exceptions are not 187*7c478bd9Sstevel@tonic-gate * implemented. 188*7c478bd9Sstevel@tonic-gate * 189*7c478bd9Sstevel@tonic-gate * The Sun Microsystems C++ runtime contains the routine 190*7c478bd9Sstevel@tonic-gate * 191*7c478bd9Sstevel@tonic-gate * _ex_unwind(_Unwind_Stop_fn sfunc, void *sfunc_arg) 192*7c478bd9Sstevel@tonic-gate * 193*7c478bd9Sstevel@tonic-gate * which is a wrapper around _Unwind_ForcedUnwind that 194*7c478bd9Sstevel@tonic-gate * sets up a C++ exception object. 195*7c478bd9Sstevel@tonic-gate * 196*7c478bd9Sstevel@tonic-gate * Once this path is taken, the stack frame from which 197*7c478bd9Sstevel@tonic-gate * _Unwind_ForcedUnwind was called is not guaranteed to 198*7c478bd9Sstevel@tonic-gate * still exist. Thus the return codes listed below which 199*7c478bd9Sstevel@tonic-gate * result in that call returning are rendered bogus. 200*7c478bd9Sstevel@tonic-gate * 201*7c478bd9Sstevel@tonic-gate * A thread reaching the end of the stack during cancellation 202*7c478bd9Sstevel@tonic-gate * must die instead of returning _URC_END_OF_STACK. 203*7c478bd9Sstevel@tonic-gate */ 204*7c478bd9Sstevel@tonic-gate break; 205*7c478bd9Sstevel@tonic-gate case _URC_CONTINUE_UNWIND: 206*7c478bd9Sstevel@tonic-gate /* 207*7c478bd9Sstevel@tonic-gate * framework will move one frame back the stack and 208*7c478bd9Sstevel@tonic-gate * call here with updated context 209*7c478bd9Sstevel@tonic-gate * 210*7c478bd9Sstevel@tonic-gate * The exception record supplied to _Unwind_ForcedUnwind 211*7c478bd9Sstevel@tonic-gate * need only contain the header and may be stack allocated 212*7c478bd9Sstevel@tonic-gate * if this function will never allow the personality 213*7c478bd9Sstevel@tonic-gate * function to run (as in a trace generator). 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate break; 216*7c478bd9Sstevel@tonic-gate case _URC_INSTALL_CONTEXT: 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * framework will resume execution of user code at location 219*7c478bd9Sstevel@tonic-gate * specified by (altered) context 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate _Unwind_Delete_Exception(res, exception_object); 222*7c478bd9Sstevel@tonic-gate break; 223*7c478bd9Sstevel@tonic-gate case _URC_NORMAL_STOP: 224*7c478bd9Sstevel@tonic-gate /* 225*7c478bd9Sstevel@tonic-gate * call to _Unwind_ForcedUnwind will return _URC_NORMAL_STOP 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate _Unwind_Delete_Exception(res, exception_object); 228*7c478bd9Sstevel@tonic-gate break; 229*7c478bd9Sstevel@tonic-gate case _URC_END_OF_STACK: 230*7c478bd9Sstevel@tonic-gate /* 231*7c478bd9Sstevel@tonic-gate * call to _Unwind_ForcedUnwind will return _URC_END_OF_STACK 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate _Unwind_Delete_Exception(res, exception_object); 234*7c478bd9Sstevel@tonic-gate break; 235*7c478bd9Sstevel@tonic-gate case _URC_FOREIGN_EXCEPTION_CAUGHT: 236*7c478bd9Sstevel@tonic-gate case _URC_FATAL_PHASE2_ERROR: 237*7c478bd9Sstevel@tonic-gate case _URC_FATAL_PHASE1_ERROR: 238*7c478bd9Sstevel@tonic-gate case _URC_HANDLER_FOUND: 239*7c478bd9Sstevel@tonic-gate /* 240*7c478bd9Sstevel@tonic-gate * call to _Unwind_ForcedUnwind will return 241*7c478bd9Sstevel@tonic-gate * _URC_FATAL_PHASE2_ERROR 242*7c478bd9Sstevel@tonic-gate */ 243*7c478bd9Sstevel@tonic-gate _Unwind_Delete_Exception(res, exception_object); 244*7c478bd9Sstevel@tonic-gate break; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate return (res); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate #endif 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * Stack frame context accessors defined in ABI 253*7c478bd9Sstevel@tonic-gate * (despite all the dire text in the ABI these are reliable Get/Set routines) 254*7c478bd9Sstevel@tonic-gate * Note: RA is handled as a GR value 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * Valid Index values for _Unwind_GetGR 259*7c478bd9Sstevel@tonic-gate */ 260*7c478bd9Sstevel@tonic-gate #define GPR_RBX 3 /* callee saves */ 261*7c478bd9Sstevel@tonic-gate #define FP_RBP 6 /* callee saves (optional frame pointer) */ 262*7c478bd9Sstevel@tonic-gate #define SP_RSP 7 /* callee saves */ 263*7c478bd9Sstevel@tonic-gate #define EIR_R12 12 /* callee saves */ 264*7c478bd9Sstevel@tonic-gate #define EIR_R13 13 /* callee saves */ 265*7c478bd9Sstevel@tonic-gate #define EIR_R14 14 /* callee saves */ 266*7c478bd9Sstevel@tonic-gate #define EIR_R15 15 /* callee saves */ 267*7c478bd9Sstevel@tonic-gate #define RET_ADD 16 /* virtual register - really caller's PC */ 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate /* 270*7c478bd9Sstevel@tonic-gate * Valid Index values for _Unwind_SetGR 271*7c478bd9Sstevel@tonic-gate */ 272*7c478bd9Sstevel@tonic-gate #define GPR_RDX 1 /* landing pad parameter */ 273*7c478bd9Sstevel@tonic-gate #define GPR_RCX 2 /* landing pad parameter */ 274*7c478bd9Sstevel@tonic-gate #define GPR_RSI 4 /* landing pad parameter */ 275*7c478bd9Sstevel@tonic-gate #define GPR_RDI 5 /* landing pad parameter */ 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate uint64_t _Unwind_GetGR(struct _Unwind_Context *context, int index); 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate void _Unwind_SetGR(struct _Unwind_Context *context, int index, 280*7c478bd9Sstevel@tonic-gate uint64_t new_value); 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate uint64_t _Unwind_GetCFA(struct _Unwind_Context *context); 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate uint64_t _Unwind_GetIP(struct _Unwind_Context *context); 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate void _Unwind_SetIP(struct _Unwind_Context *context, uint64_t new_value); 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate void *_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context); 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate uint64_t _Unwind_GetRegionStart(struct _Unwind_Context *context); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate #endif /* __amd64 */ 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate #endif 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate #endif /* _STACK_UNWIND_H */ 299