diff options
author | hp.com!davidm <hp.com!davidm> | 2004-10-15 13:53:29 +0000 |
---|---|---|
committer | hp.com!davidm <hp.com!davidm> | 2004-10-15 13:53:29 +0000 |
commit | 07e9f4df8922b98da6c62ada5619e1b27ce0fccb (patch) | |
tree | 4383d0feac29fd4a9151e7ab55630bd61f61fa31 /tests | |
parent | e4d5a228124d967da1fa4267744cf57138e7b0c4 (diff) | |
download | libunwind-07e9f4df8922b98da6c62ada5619e1b27ce0fccb.tar.gz |
Include "config.h" if we have it.
Include <errno.h>.
Include <ia64intrin.h> if we have it.
(get_bsp): New function.
(doit): Use get_bsp() instead of __builtin_ia64_bsp().
(main): Replace %m with %s/strerror(errno).
(Logical change 1.277)
Diffstat (limited to 'tests')
-rw-r--r-- | tests/ia64-test-setjmp.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/tests/ia64-test-setjmp.c b/tests/ia64-test-setjmp.c index e69de29b..a32557a8 100644 --- a/tests/ia64-test-setjmp.c +++ b/tests/ia64-test-setjmp.c @@ -0,0 +1,142 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang <davidm@hpl.hp.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Test to verify that we can siglongjmp() into a frame whose register + window is not backed by valid memory. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <errno.h> +#include <stdio.h> +#include <stdint.h> +#include <setjmp.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> + +#include <sys/mman.h> + +#ifdef HAVE_IA64INTRIN_H +# include <ia64intrin.h> +#endif + +static sigjmp_buf env; +static int return_level; +static uintptr_t return_bsp; +static int verbose; + +uintptr_t +get_bsp (void) +{ +#ifdef __INTEL_COMPILER + return __getReg (_IA64_REG_AR_BSP); +#else + return (uintptr_t) __builtin_ia64_bsp (); +#endif +} + +static void +sighandler (int signal, void *siginfo, void *sigcontext) +{ + ucontext_t *uc = sigcontext; + int local = 0; + + if (verbose) + printf ("got signal, stack at %p, saved bsp=0x%lx\n", + &local, uc->uc_mcontext.sc_ar_bsp); + siglongjmp (env, 1); +} + +static void +doit (int n) +{ + uintptr_t guard_page_addr, bsp = get_bsp (); + + if (n == 0) + { + size_t page_size = getpagesize (); + + guard_page_addr = (bsp + page_size - 1) & -page_size; + if (verbose) + printf ("guard_page_addr = 0x%lx\n", (unsigned long) guard_page_addr); + if (mmap ((void *) guard_page_addr, page_size, PROT_NONE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0) != (void *) guard_page_addr) + { + perror ("mmap"); + exit (EXIT_FAILURE); + } + } + + if (sigsetjmp (env, 1)) + { + return_level = n; + return_bsp = bsp; + } + else + doit (n + 1); +} + +int +main (int argc, char **argv) +{ + struct sigaction sa; + stack_t ss; + + if (argc > 1) + verbose = 1; + + ss.ss_sp = malloc (2 * SIGSTKSZ); + if (ss.ss_sp == NULL) + { + puts ("failed to allocate alternate stack"); + return EXIT_FAILURE; + } + ss.ss_flags = 0; + ss.ss_size = 2 * SIGSTKSZ; + if (sigaltstack (&ss, NULL) < 0) + { + printf ("sigaltstack failed: %s\n", strerror (errno)); + return EXIT_FAILURE; + } + + sa.sa_handler = (void (*) (int)) sighandler; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_ONSTACK; + if (sigaction (SIGSEGV, &sa, NULL) < 0) + { + printf ("sigaction failed: %s\n", strerror (errno)); + exit (1); + } + + doit (0); + + if (verbose) + { + printf ("sigsetjmp returned at level %d bsp=0x%lx\n", + return_level, return_bsp); + puts ("Test succeeded!"); + } + return EXIT_SUCCESS; +} |