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