hp.com!davidm | ab0fdbb | 2003-12-04 07:44:21 +0000 | [diff] [blame] | 1 | /* libunwind - a platform-independent unwind library |
| 2 | Copyright (C) 2003 Hewlett-Packard Co |
| 3 | Contributed by David Mosberger-Tang <davidm@hpl.hp.com> |
| 4 | |
| 5 | This file is part of libunwind. |
| 6 | |
| 7 | Permission is hereby granted, free of charge, to any person obtaining |
| 8 | a copy of this software and associated documentation files (the |
| 9 | "Software"), to deal in the Software without restriction, including |
| 10 | without limitation the rights to use, copy, modify, merge, publish, |
| 11 | distribute, sublicense, and/or sell copies of the Software, and to |
| 12 | permit persons to whom the Software is furnished to do so, subject to |
| 13 | the following conditions: |
| 14 | |
| 15 | The above copyright notice and this permission notice shall be |
| 16 | included in all copies or substantial portions of the Software. |
| 17 | |
| 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 22 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 24 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 25 | |
| 26 | #include "unwind-internal.h" |
| 27 | |
hp.com!davidm | c4f5974 | 2004-01-03 10:50:24 +0000 | [diff] [blame^] | 28 | PROTECTED _Unwind_Reason_Code |
hp.com!davidm | ab0fdbb | 2003-12-04 07:44:21 +0000 | [diff] [blame] | 29 | _Unwind_RaiseException (struct _Unwind_Exception *exception_object) |
| 30 | { |
| 31 | unsigned long exception_class = exception_object->exception_class; |
| 32 | _Unwind_Personality_Fn personality; |
| 33 | struct _Unwind_Context context; |
| 34 | _Unwind_Reason_Code reason; |
| 35 | unw_proc_info_t pi; |
| 36 | unw_context_t uc; |
| 37 | unw_word_t ip; |
| 38 | int ret; |
| 39 | |
| 40 | debug (1, "%s(exception_object=%p)\n", __FUNCTION__, exception_object); |
| 41 | |
| 42 | if (_Unwind_InitContext (&context, &uc) < 0) |
| 43 | return _URC_FATAL_PHASE1_ERROR; |
| 44 | |
| 45 | /* Phase 1 (search phase) */ |
| 46 | |
| 47 | while (1) |
| 48 | { |
| 49 | if ((ret = unw_step (&context.cursor)) <= 0) |
| 50 | { |
| 51 | if (ret == 0) |
| 52 | { |
| 53 | debug (1, "%s: no handler found\n", __FUNCTION__); |
| 54 | return _URC_END_OF_STACK; |
| 55 | } |
| 56 | else |
| 57 | return _URC_FATAL_PHASE1_ERROR; |
| 58 | } |
| 59 | |
| 60 | if (unw_get_proc_info (&context.cursor, &pi) < 0) |
| 61 | return _URC_FATAL_PHASE1_ERROR; |
| 62 | |
| 63 | personality = (_Unwind_Personality_Fn) pi.handler; |
| 64 | if (personality) |
| 65 | { |
| 66 | reason = (*personality) (_U_VERSION, _UA_SEARCH_PHASE, |
| 67 | exception_class, exception_object, |
| 68 | &context); |
| 69 | if (reason != _URC_CONTINUE_UNWIND) |
| 70 | { |
| 71 | if (reason == _URC_HANDLER_FOUND) |
| 72 | break; |
| 73 | else |
| 74 | { |
| 75 | debug (1, "%s: personality returned %d\n", |
| 76 | __FUNCTION__, reason); |
| 77 | return _URC_FATAL_PHASE1_ERROR; |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | /* Exceptions are associated with IP-ranges. If a given exception |
| 84 | is handled at a particular IP, it will _always_ be handled at |
| 85 | that IP. If this weren't true, we'd have to track the tuple |
| 86 | (IP,SP,BSP) to uniquely identify the stack frame that's handling |
| 87 | the exception. */ |
| 88 | if (unw_get_reg (&context.cursor, UNW_REG_IP, &ip) < 0) |
| 89 | return _URC_FATAL_PHASE1_ERROR; |
| 90 | exception_object->private_1 = 0; /* clear "stop" pointer */ |
| 91 | exception_object->private_2 = ip; /* save frame marker */ |
| 92 | |
| 93 | debug (1, "%s: found handler for IP=%lx; entering cleanup phase\n", |
| 94 | __FUNCTION__, ip); |
| 95 | |
| 96 | /* Reset the cursor to the first frame: */ |
| 97 | if (unw_init_local (&context.cursor, &uc) < 0) |
| 98 | return _URC_FATAL_PHASE1_ERROR; |
| 99 | |
| 100 | return _Unwind_Phase2 (exception_object, &context); |
| 101 | } |