Gtest-exc.c revision 797322b3b461c7e71d1d072227b5aa65a9ff31fa
1/* libunwind - a platform-independent unwind library 2 Copyright (C) 2001-2003 Hewlett-Packard Co 3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 4 5Permission is hereby granted, free of charge, to any person obtaining 6a copy of this software and associated documentation files (the 7"Software"), to deal in the Software without restriction, including 8without limitation the rights to use, copy, modify, merge, publish, 9distribute, sublicense, and/or sell copies of the Software, and to 10permit persons to whom the Software is furnished to do so, subject to 11the following conditions: 12 13The above copyright notice and this permission notice shall be 14included in all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23 24/* This illustrates the basics of using the unwind interface for 25 exception handling. */ 26 27#include <stdio.h> 28#include <stdlib.h> 29#include <unistd.h> 30 31#include <libunwind.h> 32 33#define panic(args...) \ 34 { ++nerrors; fprintf (stderr, args); } 35 36int nerrors = 0; 37int verbose = 0; 38 39static void b (void *); 40 41static void 42raise_exception (void *addr) 43{ 44 unw_cursor_t cursor; 45 unw_word_t ip; 46 unw_context_t uc; 47 48 unw_getcontext (&uc); 49 if (unw_init_local (&cursor, &uc) < 0) 50 { 51 panic ("unw_init_local() failed!\n"); 52 return; 53 } 54 55 /* unwind to frame b(): */ 56 if (unw_step (&cursor) < 0) 57 { 58 panic ("unw_step() failed!\n"); 59 return; 60 } 61 62 /* unwind to frame a(): */ 63 if (unw_step (&cursor) < 0) 64 { 65 panic ("unw_step() failed!\n"); 66 return; 67 } 68 69 unw_get_reg (&cursor, UNW_REG_IP, &ip); 70 if (verbose) 71 printf ("old ip = %lx, new ip = %p\n", (long) ip, addr); 72 73 if (unw_set_reg (&cursor, UNW_REG_IP, (unw_word_t) addr) < 0) 74 { 75 panic ("unw_set_reg() failed!\n"); 76 return; 77 } 78 79 unw_resume (&cursor); /* transfer control to exception handler */ 80} 81 82#if !UNW_TARGET_IA64 83 84void * 85__builtin_ia64_bsp (void) 86{ 87 return NULL; 88} 89 90#endif 91 92static int 93a (void) 94{ 95 long stack; 96 97#ifdef __GNUC__ 98 if (verbose) 99 printf ("a: sp=%p bsp=%p\n", &stack, __builtin_ia64_bsp ()); 100 b (&&handler); 101 panic ("FAILURE: unexpected return from func()!\n"); 102 103#if UNW_TARGET_IA64 104 asm volatile ("1:"); /* force a new bundle */ 105#endif 106 handler: 107 if (verbose) 108 { 109 printf ("exception handler: here we go (sp=%p, bsp=%p)...\n", 110 &stack, __builtin_ia64_bsp ()); 111 /* This call works around a bug in gcc (up-to pre3.4) which 112 causes invalid assembly code to be generated when 113 __builtin_ia64_bsp() gets predicated. */ 114 getpid (); 115 } 116#else 117 if (verbose) 118 printf ("a: this test only works with GNU C compiler.\n"); 119#endif 120 return 0; 121} 122 123static void 124b (void *addr) 125{ 126 if (verbose) 127 printf ("b() calling raise_exception()\n"); 128 raise_exception (addr); 129 panic ("FAILURE: b() returned from raise_exception()!!\n"); 130} 131 132int 133main (int argc, char **argv) 134{ 135 if (argc > 1) 136 ++verbose; 137 138 if (a () != 0 || nerrors > 0) 139 { 140 fprintf (stderr, "FAILURE: test failed; try again?\n"); 141 exit (-1); 142 } 143 144 if (verbose) 145 printf ("SUCCESS!\n"); 146 return 0; 147} 148