17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Public interfaces for AMD64 Unwind routines 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #ifndef _STACK_UNWIND_H 327c478bd9Sstevel@tonic-gate #define _STACK_UNWIND_H 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #ifdef __cplusplus 377c478bd9Sstevel@tonic-gate extern "C" { 387c478bd9Sstevel@tonic-gate #endif 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #if defined(__amd64) /* none of this is valid except for AMD64 */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate typedef enum { 437c478bd9Sstevel@tonic-gate _URC_NO_REASON = 0, 447c478bd9Sstevel@tonic-gate _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 457c478bd9Sstevel@tonic-gate _URC_FATAL_PHASE2_ERROR = 2, 467c478bd9Sstevel@tonic-gate _URC_FATAL_PHASE1_ERROR = 3, 477c478bd9Sstevel@tonic-gate _URC_NORMAL_STOP = 4, 487c478bd9Sstevel@tonic-gate _URC_END_OF_STACK = 5, 497c478bd9Sstevel@tonic-gate _URC_HANDLER_FOUND = 6, 507c478bd9Sstevel@tonic-gate _URC_INSTALL_CONTEXT = 7, 517c478bd9Sstevel@tonic-gate _URC_CONTINUE_UNWIND = 8 527c478bd9Sstevel@tonic-gate } _Unwind_Reason_Code; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate typedef int _Unwind_Action; 557c478bd9Sstevel@tonic-gate extern const _Unwind_Action _UA_SEARCH_PHASE; 567c478bd9Sstevel@tonic-gate extern const _Unwind_Action _UA_CLEANUP_PHASE; 577c478bd9Sstevel@tonic-gate extern const _Unwind_Action _UA_HANDLER_FRAME; 587c478bd9Sstevel@tonic-gate extern const _Unwind_Action _UA_FORCE_UNWIND; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate struct _Unwind_Exception; 617c478bd9Sstevel@tonic-gate struct _Unwind_Context; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * Signature of language specific call back for deleting exception object 667c478bd9Sstevel@tonic-gate */ 677c478bd9Sstevel@tonic-gate typedef void (*_Unwind_Exception_Cleanup_Fn)( 687c478bd9Sstevel@tonic-gate _Unwind_Reason_Code reason, 697c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exc); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * Header preceding language specific exception object 737c478bd9Sstevel@tonic-gate * For Sun C++ these fields are the beginning of the 747c478bd9Sstevel@tonic-gate * language specific structure. 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate struct _Unwind_Exception { 777c478bd9Sstevel@tonic-gate uint64_t exception_class; 787c478bd9Sstevel@tonic-gate _Unwind_Exception_Cleanup_Fn exception_cleanup; 797c478bd9Sstevel@tonic-gate uint64_t private_1; 807c478bd9Sstevel@tonic-gate uint64_t private_2; 817c478bd9Sstevel@tonic-gate }; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * Signature for language specific routine - address is in eh_frame CIE. 857c478bd9Sstevel@tonic-gate * During phase one it predicts whether exception would be caught at this 867c478bd9Sstevel@tonic-gate * frame and during phase two selects a handler as predicted. An action 877c478bd9Sstevel@tonic-gate * of _UA_FORCE_UNWIND will prevent any catch block from being selected. 887c478bd9Sstevel@tonic-gate * 897c478bd9Sstevel@tonic-gate * The personality function is the only call back used when 907c478bd9Sstevel@tonic-gate * _Unwind_RaiseException() is called. 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( 937c478bd9Sstevel@tonic-gate int version, 947c478bd9Sstevel@tonic-gate _Unwind_Action actions, 957c478bd9Sstevel@tonic-gate uint64_t exceptionClass, 967c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exceptionObject, 977c478bd9Sstevel@tonic-gate struct _Unwind_Context *context); 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * Signature of callback function that is used when _Unwind_ForcedUnwind() 1017c478bd9Sstevel@tonic-gate * is called. It is called at every step of walkback and that can control 1027c478bd9Sstevel@tonic-gate * the execution of the personality routine at each frame. 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)( 1057c478bd9Sstevel@tonic-gate int version, 1067c478bd9Sstevel@tonic-gate _Unwind_Action actions, 1077c478bd9Sstevel@tonic-gate uint64_t exceptionClass, 1087c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exceptionObject, 1097c478bd9Sstevel@tonic-gate struct _Unwind_Context *context, 1107c478bd9Sstevel@tonic-gate void *stop_parameter); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* 1137c478bd9Sstevel@tonic-gate * Here begins the external functional interface 1147c478bd9Sstevel@tonic-gate */ 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* 1177c478bd9Sstevel@tonic-gate * Used to implement C++ throw - starts walkback with caller's caller. 1187c478bd9Sstevel@tonic-gate * The routine in the middle must use %rbp as a frame pointer 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate _Unwind_Reason_Code _Unwind_RaiseException( 1217c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exception_object); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Used (with different stop functions) for POSIX thread cancellation 1257c478bd9Sstevel@tonic-gate * and stack walking - starts walkback with caller's caller. 1267c478bd9Sstevel@tonic-gate * 1277c478bd9Sstevel@tonic-gate * Note: must be called by a routine which has a real FP and doesn't use 1287c478bd9Sstevel@tonic-gate * callee saves registers. 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate _Unwind_Reason_Code _Unwind_ForcedUnwind( 1317c478bd9Sstevel@tonic-gate struct _Unwind_Exception *exception_object, 1327c478bd9Sstevel@tonic-gate _Unwind_Stop_Fn stop, 1337c478bd9Sstevel@tonic-gate void *stop_parameter); 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Used to resume unwinding at end of cleanup (not catch) code 1377c478bd9Sstevel@tonic-gate * Assumes that caller is language specific cleanup code and 1387c478bd9Sstevel@tonic-gate * pops the stack one level before resuming walk. 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate void _Unwind_Resume(struct _Unwind_Exception *exception_object); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Calls destructor function for exception object 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate void _Unwind_DeleteException(struct _Unwind_Exception *exception_object); 1467c478bd9Sstevel@tonic-gate /* 1477c478bd9Sstevel@tonic-gate * { 148*6e270ca8SMarcel Telka * (*(exception_object->exception_cleanup))(_URC_NO_REASON, 149*6e270ca8SMarcel Telka * exception_object); 1507c478bd9Sstevel@tonic-gate * } 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate #if 0 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate extern "C" _Unwind_Reason_Code 1577c478bd9Sstevel@tonic-gate __example_stop_fn(int version, int actions, uint64_t exclass, 158*6e270ca8SMarcel Telka struct _Unwind_Exception *exception_object, 159*6e270ca8SMarcel Telka struct _Unwind_Context *ctx, void *_Sa) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate _Unwind_Reason_Code res; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate uint64_t fp = _Unwind_GetCFA(ctx); 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate if (fp == 0 || _Unwind_GetGR(ctx, RET_ADD) == 0) { 1667c478bd9Sstevel@tonic-gate if (no_return) 1677c478bd9Sstevel@tonic-gate die; 1687c478bd9Sstevel@tonic-gate res = _URC_END_OF_STACK; 1697c478bd9Sstevel@tonic-gate } else { 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * Your logic here: 1727c478bd9Sstevel@tonic-gate * res = ........ 1737c478bd9Sstevel@tonic-gate */ 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate switch (res) { 1767c478bd9Sstevel@tonic-gate case _URC_NO_REASON: 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * framework will call personality routine for current context 1797c478bd9Sstevel@tonic-gate * then then move one frame back the stack and call here with 1807c478bd9Sstevel@tonic-gate * updated context. POSIX thread cancellation uses this pattern. 1817c478bd9Sstevel@tonic-gate * 1827c478bd9Sstevel@tonic-gate * If this path is taken the exception object passed must have 1837c478bd9Sstevel@tonic-gate * been constructed by the same language system supplying the 1847c478bd9Sstevel@tonic-gate * personality routines. i.e. foreign exceptions are not 1857c478bd9Sstevel@tonic-gate * implemented. 1867c478bd9Sstevel@tonic-gate * 1877c478bd9Sstevel@tonic-gate * The Sun Microsystems C++ runtime contains the routine 1887c478bd9Sstevel@tonic-gate * 1897c478bd9Sstevel@tonic-gate * _ex_unwind(_Unwind_Stop_fn sfunc, void *sfunc_arg) 1907c478bd9Sstevel@tonic-gate * 1917c478bd9Sstevel@tonic-gate * which is a wrapper around _Unwind_ForcedUnwind that 1927c478bd9Sstevel@tonic-gate * sets up a C++ exception object. 1937c478bd9Sstevel@tonic-gate * 1947c478bd9Sstevel@tonic-gate * Once this path is taken, the stack frame from which 1957c478bd9Sstevel@tonic-gate * _Unwind_ForcedUnwind was called is not guaranteed to 1967c478bd9Sstevel@tonic-gate * still exist. Thus the return codes listed below which 1977c478bd9Sstevel@tonic-gate * result in that call returning are rendered bogus. 1987c478bd9Sstevel@tonic-gate * 1997c478bd9Sstevel@tonic-gate * A thread reaching the end of the stack during cancellation 2007c478bd9Sstevel@tonic-gate * must die instead of returning _URC_END_OF_STACK. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate break; 2037c478bd9Sstevel@tonic-gate case _URC_CONTINUE_UNWIND: 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * framework will move one frame back the stack and 2067c478bd9Sstevel@tonic-gate * call here with updated context 2077c478bd9Sstevel@tonic-gate * 2087c478bd9Sstevel@tonic-gate * The exception record supplied to _Unwind_ForcedUnwind 2097c478bd9Sstevel@tonic-gate * need only contain the header and may be stack allocated 2107c478bd9Sstevel@tonic-gate * if this function will never allow the personality 2117c478bd9Sstevel@tonic-gate * function to run (as in a trace generator). 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate break; 2147c478bd9Sstevel@tonic-gate case _URC_INSTALL_CONTEXT: 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * framework will resume execution of user code at location 2177c478bd9Sstevel@tonic-gate * specified by (altered) context 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate _Unwind_Delete_Exception(res, exception_object); 2207c478bd9Sstevel@tonic-gate break; 2217c478bd9Sstevel@tonic-gate case _URC_NORMAL_STOP: 2227c478bd9Sstevel@tonic-gate /* 2237c478bd9Sstevel@tonic-gate * call to _Unwind_ForcedUnwind will return _URC_NORMAL_STOP 2247c478bd9Sstevel@tonic-gate */ 2257c478bd9Sstevel@tonic-gate _Unwind_Delete_Exception(res, exception_object); 2267c478bd9Sstevel@tonic-gate break; 2277c478bd9Sstevel@tonic-gate case _URC_END_OF_STACK: 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * call to _Unwind_ForcedUnwind will return _URC_END_OF_STACK 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate _Unwind_Delete_Exception(res, exception_object); 2327c478bd9Sstevel@tonic-gate break; 2337c478bd9Sstevel@tonic-gate case _URC_FOREIGN_EXCEPTION_CAUGHT: 2347c478bd9Sstevel@tonic-gate case _URC_FATAL_PHASE2_ERROR: 2357c478bd9Sstevel@tonic-gate case _URC_FATAL_PHASE1_ERROR: 2367c478bd9Sstevel@tonic-gate case _URC_HANDLER_FOUND: 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * call to _Unwind_ForcedUnwind will return 2397c478bd9Sstevel@tonic-gate * _URC_FATAL_PHASE2_ERROR 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate _Unwind_Delete_Exception(res, exception_object); 2427c478bd9Sstevel@tonic-gate break; 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate return (res); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate #endif 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate /* 2507c478bd9Sstevel@tonic-gate * Stack frame context accessors defined in ABI 2517c478bd9Sstevel@tonic-gate * (despite all the dire text in the ABI these are reliable Get/Set routines) 2527c478bd9Sstevel@tonic-gate * Note: RA is handled as a GR value 2537c478bd9Sstevel@tonic-gate */ 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /* 2567c478bd9Sstevel@tonic-gate * Valid Index values for _Unwind_GetGR 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate #define GPR_RBX 3 /* callee saves */ 2597c478bd9Sstevel@tonic-gate #define FP_RBP 6 /* callee saves (optional frame pointer) */ 2607c478bd9Sstevel@tonic-gate #define SP_RSP 7 /* callee saves */ 2617c478bd9Sstevel@tonic-gate #define EIR_R12 12 /* callee saves */ 2627c478bd9Sstevel@tonic-gate #define EIR_R13 13 /* callee saves */ 2637c478bd9Sstevel@tonic-gate #define EIR_R14 14 /* callee saves */ 2647c478bd9Sstevel@tonic-gate #define EIR_R15 15 /* callee saves */ 2657c478bd9Sstevel@tonic-gate #define RET_ADD 16 /* virtual register - really caller's PC */ 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * Valid Index values for _Unwind_SetGR 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate #define GPR_RDX 1 /* landing pad parameter */ 2717c478bd9Sstevel@tonic-gate #define GPR_RCX 2 /* landing pad parameter */ 2727c478bd9Sstevel@tonic-gate #define GPR_RSI 4 /* landing pad parameter */ 2737c478bd9Sstevel@tonic-gate #define GPR_RDI 5 /* landing pad parameter */ 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate uint64_t _Unwind_GetGR(struct _Unwind_Context *context, int index); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate void _Unwind_SetGR(struct _Unwind_Context *context, int index, 2787c478bd9Sstevel@tonic-gate uint64_t new_value); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate uint64_t _Unwind_GetCFA(struct _Unwind_Context *context); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate uint64_t _Unwind_GetIP(struct _Unwind_Context *context); 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate void _Unwind_SetIP(struct _Unwind_Context *context, uint64_t new_value); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate void *_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context); 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate uint64_t _Unwind_GetRegionStart(struct _Unwind_Context *context); 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate #endif /* __amd64 */ 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate #ifdef __cplusplus 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate #endif 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate #endif /* _STACK_UNWIND_H */ 297