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