107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm/* libunwind - a platform-independent unwind library
207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm   Copyright (C) 2004 Hewlett-Packard Co
307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmPermission is hereby granted, free of charge, to any person obtaining
607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidma copy of this software and associated documentation files (the
707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm"Software"), to deal in the Software without restriction, including
807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
1007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmpermit persons to whom the Software is furnished to do so, subject to
1107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmthe following conditions:
1207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
1307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmThe above copyright notice and this permission notice shall be
1407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmincluded in all copies or substantial portions of the Software.
1507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
1607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
2007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
2307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
2407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm/* Test to verify that we can siglongjmp() into a frame whose register
2507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm   window is not backed by valid memory.  */
2607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
2707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#ifdef HAVE_CONFIG_H
2807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm# include "config.h"
2907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#endif
3007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
3107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#include <errno.h>
3207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#include <stdio.h>
3307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#include <stdint.h>
3407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#include <setjmp.h>
3507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#include <signal.h>
3607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#include <stdlib.h>
3783b02fa05b0b228a86e1055466447de312ff44a0hp.com!davidm#include <string.h>
3807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#include <unistd.h>
3907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
4007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#include <sys/mman.h>
4107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
4207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#ifdef HAVE_IA64INTRIN_H
4307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm# include <ia64intrin.h>
4407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#endif
4507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
4607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmstatic sigjmp_buf env;
4707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmstatic int return_level;
4807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmstatic uintptr_t return_bsp;
4907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmstatic int verbose;
5007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
5107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmuintptr_t
5207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmget_bsp (void)
5307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm{
5407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#ifdef __INTEL_COMPILER
5507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  return __getReg (_IA64_REG_AR_BSP);
5607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#else
5707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  return (uintptr_t) __builtin_ia64_bsp ();
5807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm#endif
5907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm}
6007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
6107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmstatic void
6207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmsighandler (int signal, void *siginfo, void *sigcontext)
6307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm{
6407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  ucontext_t *uc = sigcontext;
6507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  int local = 0;
6607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
6707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  if (verbose)
6807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    printf ("got signal, stack at %p, saved bsp=0x%lx\n",
6907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm	    &local, uc->uc_mcontext.sc_ar_bsp);
7007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  siglongjmp (env, 1);
7107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm}
7207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
73565ffdb75c36b7ba190610b5033f4986fd87e3b9Jan Kratochvil/* Direct call of doit () at the end of doit () would get optimized by GCC to
74565ffdb75c36b7ba190610b5033f4986fd87e3b9Jan Kratochvil   a branch.  */
75565ffdb75c36b7ba190610b5033f4986fd87e3b9Jan Kratochvilstatic void doit (int n);
7623fdda6a28d31abfcda42567cc455bd46a4fc0d0Tommi Rantalatypedef void (*doit_type) (int);
7723fdda6a28d31abfcda42567cc455bd46a4fc0d0Tommi Rantalastatic volatile doit_type doit_pointer = doit;
78565ffdb75c36b7ba190610b5033f4986fd87e3b9Jan Kratochvil
7907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmstatic void
8007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmdoit (int n)
8107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm{
8207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  uintptr_t guard_page_addr, bsp = get_bsp ();
8325739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang  void *ret;
8407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
8507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  if (n == 0)
8607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    {
8707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      size_t page_size = getpagesize ();
8807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
8907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      guard_page_addr = (bsp + page_size - 1) & -page_size;
9007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      if (verbose)
9107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm	printf ("guard_page_addr = 0x%lx\n", (unsigned long) guard_page_addr);
9225739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang      ret = mmap ((void *) guard_page_addr, page_size, PROT_NONE,
9325739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
9425739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang      if (ret != (void *) guard_page_addr)
9507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm	{
9625739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang	  if (ret == MAP_FAILED)
9725739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang	    perror ("mmap");
9825739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang	  else
9925739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang	    fprintf (stderr, "mmap() returned %p, expected 0x%lx\n",
10025739eec8667ae3a78a62b44a912a7fbcda3d43dDavid Mosberger-Tang		     ret, guard_page_addr);
10107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm	  exit (EXIT_FAILURE);
10207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm	}
10307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    }
10407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
10507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  if (sigsetjmp (env, 1))
10607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    {
10707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      return_level = n;
10807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      return_bsp = bsp;
10907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    }
11007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  else
111565ffdb75c36b7ba190610b5033f4986fd87e3b9Jan Kratochvil    (*doit_pointer) (n + 1);
11207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm}
11307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
11407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmint
11507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidmmain (int argc, char **argv)
11607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm{
11707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  struct sigaction sa;
11807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  stack_t ss;
11907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
12007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  if (argc > 1)
12107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    verbose = 1;
12207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
12307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  ss.ss_sp = malloc (2 * SIGSTKSZ);
12407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  if (ss.ss_sp == NULL)
12507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    {
12607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      puts ("failed to allocate alternate stack");
12707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      return EXIT_FAILURE;
12807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    }
12907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  ss.ss_flags = 0;
13007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  ss.ss_size = 2 * SIGSTKSZ;
13107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  if (sigaltstack (&ss, NULL) < 0)
13207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    {
13307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      printf ("sigaltstack failed: %s\n", strerror (errno));
13407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      return EXIT_FAILURE;
13507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    }
13607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
13707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  sa.sa_handler = (void (*) (int)) sighandler;
13807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  sigemptyset (&sa.sa_mask);
13907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
14007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  if (sigaction (SIGSEGV, &sa, NULL) < 0)
14107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    {
14207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      printf ("sigaction failed: %s\n", strerror (errno));
14307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      exit (1);
14407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    }
14507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
14607e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  doit (0);
14707e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm
14807e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  if (verbose)
14907e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    {
15007e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      printf ("sigsetjmp returned at level %d bsp=0x%lx\n",
15107e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm	      return_level, return_bsp);
15207e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm      puts ("Test succeeded!");
15307e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm    }
15407e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm  return EXIT_SUCCESS;
15507e9f4df8922b98da6c62ada5619e1b27ce0fccbhp.com!davidm}
156