diff --git a/tests/bt.c b/tests/bt.c index e69de29b..decb1e95 100644 --- a/tests/bt.c +++ b/tests/bt.c @@ -0,0 +1,74 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +libunwind is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +libunwind is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. */ + +#include +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +static void +do_backtrace (void) +{ + unw_cursor_t cursor; + unw_word_t ip, sp; + unw_context_t uc; + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + printf ("ip=%016lx sp=%016lx\n", ip, sp); + + { + unw_word_t proc_start, handler, lsda, bsp; + + unw_get_reg (&cursor, UNW_REG_PROC_START, &proc_start); + unw_get_reg (&cursor, UNW_REG_HANDLER, &handler); + unw_get_reg (&cursor, UNW_REG_LSDA, &lsda); + unw_get_reg (&cursor, UNW_IA64_CURRENT_BSP, &bsp); + printf ("\tproc_start=%016lx handler=%lx lsda=%lx bsp=%lx\n", + proc_start, handler, lsda, bsp); + } + } + while (unw_step (&cursor) > 0); +} + +static void +foo (void) +{ + void *buffer[20]; + int i, n; + + do_backtrace (); + + n = backtrace (buffer, 20); + for (i = 0; i < n; ++i) + printf ("[%d] ip=%p\n", i, buffer[i]); +} + +int +main (int argc, char **argv) +{ + foo (); + return 0; +} diff --git a/tests/exc.c b/tests/exc.c index e69de29b..49100027 100644 --- a/tests/exc.c +++ b/tests/exc.c @@ -0,0 +1,89 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +libunwind is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +libunwind is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. */ + +/* This illustrates the basics of using the unwind interface for + exception handling. */ + +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +int true = 1; + +static void +raise_exception (void *addr) +{ + unw_cursor_t cursor; + unw_word_t ip; + unw_context_t uc; + + unw_getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local() failed!\n"); + + /* unwind to frame b(): */ + if (unw_step (&cursor) < 0) + panic ("unw_step() failed!\n"); + + /* unwind to frame a(): */ + if (unw_step (&cursor) < 0) + panic ("unw_step() failed!\n"); + + unw_get_reg (&cursor, UNW_REG_IP, &ip); + printf ("ip = %lx\n", ip); + + if (unw_set_reg (&cursor, UNW_REG_IP, (unw_word_t) addr) < 0) + panic ("unw_set_reg() failed!\n"); + + unw_resume (&cursor); /* transfer control to exception handler */ +} + +static void +b (void *addr) +{ + printf ("b() calling raise_exception()\n"); + raise_exception (addr); +} + +static int +a (void) +{ + register long sp asm ("r12"); + printf("a: sp=%lx bsp=%p\n", sp, __builtin_ia64_bsp ()); + b (&&handler); + printf ("unexpected return from func()!\n"); + + if (true) + return -1; + + handler: + printf ("exception handler: here we go (sp=%lx, bsp=%p)...\n", + sp, __builtin_ia64_bsp ()); + return 0; +} + +int +main (int argc, char **argv) +{ + if (a () == 0) + printf ("test succeeded!\n"); + else + printf ("bummer: test failed; try again?\n"); + return 0; +} diff --git a/tests/sig.c b/tests/sig.c index e69de29b..94308afa 100644 --- a/tests/sig.c +++ b/tests/sig.c @@ -0,0 +1,82 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +libunwind is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +libunwind is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. */ + +/* This shows how to use the unwind interface to modify any ancestor + frame while still returning to the parent frame. */ + +#include +#include + +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +static void +sighandler (int signal) +{ + unw_cursor_t cursor, cursor2; + unw_word_t rp; + unw_context_t uc; + + printf ("caught signal %d\n", signal); + + unw_getcontext(&uc); + + if (unw_init (&cursor, &uc) < 0) + panic ("unw_init() failed!\n"); + + /* get cursor for caller of sighandler: */ + if (unw_step (&cursor) < 0) + panic ("unw_step() failed!\n"); + + cursor2 = cursor; + while (!unw_is_signal_frame (&cursor2)) + if (unw_step (&cursor2) < 0) + panic ("failed to find signal frame!\n"); + + if (unw_get_reg (&cursor2, UNW_REG_RP, &rp) < 0) + panic ("failed to get IP!\n"); + + /* skip faulting instruction (doesn't handle MLX template) */ + ++rp; + if (rp & 0x3 == 0x3) + rp += 13; + + if (unw_set_reg (&cursor2, UNW_REG_RP, rp) < 0) + panic ("failed to set IP!\n"); + + unw_resume (&cursor); /* update context & return to caller of sighandler() */ + + panic ("unexpected return from unw_resume()!\n"); +} + +static void +doit (char *p) +{ + int ch; + + ch = *p; /* trigger SIGSEGV */ + + printf ("doit: finishing execution!\n"); +} + +int +main (int argc, char **argv) +{ + signal (SIGSEGV, sighandler); + doit (0); +} diff --git a/tests/verify.c b/tests/verify.c index e69de29b..db143f5d 100644 --- a/tests/verify.c +++ b/tests/verify.c @@ -0,0 +1,137 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2001-2002 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +libunwind is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +libunwind is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. */ + +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +static void +init_state (unw_context_t *ucp) +{ + int i; + + ucp->uc_mcontext.sc_flags = 0; + + ucp->uc_mcontext.sc_ar_ccv = random (); + ucp->uc_mcontext.sc_ar_lc = random (); + ucp->uc_mcontext.sc_pr = random (); + +#if 0 + ucp->uc_mcontext.sc_ip = xxx; + ucp->uc_mcontext.sc_cfm = xxx; + ucp->uc_mcontext.sc_um = xxx; + ucp->uc_mcontext.sc_ar_rsc = xxx; + ucp->uc_mcontext.sc_ar_bsp = xxx; + ucp->uc_mcontext.sc_ar_rnat = xxx; + ucp->uc_mcontext.sc_ar_unat = xxx; + ucp->uc_mcontext.sc_ar_fpsr = xxx; + ucp->uc_mcontext.sc_ar_pfs = xxx; +#endif + + /* initialize static registers without trashing gp (r1), sp (r12), + or tp (r13). */ + for (i = 2; i < 32; ++i) + { + if (i != 12 && i != 13) + { + ucp->uc_mcontext.sc_gr[i] = random (); + ucp->uc_mcontext.sc_nat |= (random () & 1) << i; + } + } + +#if 0 + /* initialize stacked registers: */ + for (i = 32; i < 128; ++i) + { + xxx; + } +#endif + + for (i = 0; i < 8; ++i) + ucp->uc_mcontext.sc_br[i] = random (); + + for (i = 0; i < 128; ++i) + { + ucp->uc_mcontext.sc_fr[i].u.bits[0] = random (); + ucp->uc_mcontext.sc_fr[i].u.bits[0] = random (); + } +#if 0 + ucp->uc_mcontext.sc_rbs_base = xxx; + ucp->uc_mcontext.sc_loadrs = xxx; + ucp->uc_mcontext.sc_ar25 = xxx; + ucp->uc_mcontext.sc_ar26 = xxx; +#endif +} + +static void +check_state (ucontext_t *orig_state, unw_cursor_t *c) +{ + unw_word_t val; + + unw_get_reg (c, UNW_REG_IP, &val); + printf ("IP: orig=%016lx now=%016lx\n", orig_state->uc_mcontext.sc_ip, val); +} + +static void +setup_context (ucontext_t *unwind_ucp) +{ + asm volatile ("mov ar.fpsr = %0" :: "r"(0x9804c8a70033f)); + + init_state (unwind_ucp); + setcontext (unwind_ucp); +} + +static void +check (ucontext_t *unwind_ucp, ucontext_t *setup_ucp, + void (*doit) (ucontext_t *)) +{ + swapcontext (unwind_ucp, setup_ucp); + (*doit) (unwind_ucp); +} + +static void +test1 (ucontext_t *orig_state) +{ + unw_cursor_t cursor; + ucontext_t uc; + + getcontext (&uc); + if (unw_init_local (&cursor, &uc) < 0) + panic ("unw_init_local failed\n"); + + if (unw_step (&cursor) < 0) + panic ("unw_step failed\n"); + + check_state (orig_state, &cursor); +} + +int +main (int argc, char **argv) +{ + ucontext_t unwind_uc, setup_uc; + unsigned char stack_mem[256*1024]; + + setup_uc.uc_stack.ss_sp = stack_mem; + setup_uc.uc_stack.ss_flags = 0; + setup_uc.uc_stack.ss_size = sizeof (stack_mem); + makecontext (&setup_uc, (void (*) (void)) setup_context, + 2, &setup_uc, &unwind_uc); + check (&unwind_uc, &setup_uc, test1); + return 0; +}