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