1d9e100753f5694ebb14769048373e8171f336127hp.com!davidm/* libunwind - a platform-independent unwind library
2d9e100753f5694ebb14769048373e8171f336127hp.com!davidm   Copyright (C) 2003-2005 Hewlett-Packard Co
3d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
5d9e100753f5694ebb14769048373e8171f336127hp.com!davidmThis file is part of libunwind.
6d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
7d9e100753f5694ebb14769048373e8171f336127hp.com!davidmPermission is hereby granted, free of charge, to any person obtaining
8d9e100753f5694ebb14769048373e8171f336127hp.com!davidma copy of this software and associated documentation files (the
9d9e100753f5694ebb14769048373e8171f336127hp.com!davidm"Software"), to deal in the Software without restriction, including
10d9e100753f5694ebb14769048373e8171f336127hp.com!davidmwithout limitation the rights to use, copy, modify, merge, publish,
11d9e100753f5694ebb14769048373e8171f336127hp.com!davidmdistribute, sublicense, and/or sell copies of the Software, and to
12d9e100753f5694ebb14769048373e8171f336127hp.com!davidmpermit persons to whom the Software is furnished to do so, subject to
13d9e100753f5694ebb14769048373e8171f336127hp.com!davidmthe following conditions:
14d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
15d9e100753f5694ebb14769048373e8171f336127hp.com!davidmThe above copyright notice and this permission notice shall be
16d9e100753f5694ebb14769048373e8171f336127hp.com!davidmincluded in all copies or substantial portions of the Software.
17d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
18d9e100753f5694ebb14769048373e8171f336127hp.com!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19d9e100753f5694ebb14769048373e8171f336127hp.com!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20d9e100753f5694ebb14769048373e8171f336127hp.com!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21d9e100753f5694ebb14769048373e8171f336127hp.com!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22d9e100753f5694ebb14769048373e8171f336127hp.com!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23d9e100753f5694ebb14769048373e8171f336127hp.com!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24d9e100753f5694ebb14769048373e8171f336127hp.com!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
26d9e100753f5694ebb14769048373e8171f336127hp.com!davidm#define UNW_LOCAL_ONLY
27d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
28d9e100753f5694ebb14769048373e8171f336127hp.com!davidm#include <setjmp.h>
29d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
30d9e100753f5694ebb14769048373e8171f336127hp.com!davidm#include "libunwind_i.h"
31d9e100753f5694ebb14769048373e8171f336127hp.com!davidm#include "jmpbuf.h"
32d9e100753f5694ebb14769048373e8171f336127hp.com!davidm#include "setjmp_i.h"
33d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
3429c110265f50c14b8611a3f14be3941b23952125Konstantin Belousov#if !defined(_NSIG) && defined(_SIG_MAXSIG)
3529c110265f50c14b8611a3f14be3941b23952125Konstantin Belousov# define _NSIG (_SIG_MAXSIG - 1)
3629c110265f50c14b8611a3f14be3941b23952125Konstantin Belousov#endif
3729c110265f50c14b8611a3f14be3941b23952125Konstantin Belousov
382b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#if defined(__GLIBC__)
392b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#if __GLIBC_PREREQ(2, 4)
40297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov
41297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the
42297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov   register values in jmp_buf by XORing them with a "random"
43297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov   canary value.
44297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov
45297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov   This makes it impossible to implement longjmp, as we
46297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov   can never match wp[JB_SP], unless we decode the canary first.
47297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov
48297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov   Doing so is possible, but doesn't appear to be worth the trouble,
49297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov   so we simply defer to glibc siglongjmp here.  */
50297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov
512b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#define siglongjmp __nonworking_siglongjmp
52814bd79fb1814eb5bbeb2fdb652d5ae08f1edd28Arun Sharmastatic void siglongjmp (sigjmp_buf env, int val) UNUSED;
532b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#endif
542b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#endif /* __GLIBC_PREREQ */
55297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov
56d9e100753f5694ebb14769048373e8171f336127hp.com!davidmvoid
57d9e100753f5694ebb14769048373e8171f336127hp.com!davidmsiglongjmp (sigjmp_buf env, int val)
58d9e100753f5694ebb14769048373e8171f336127hp.com!davidm{
59d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  unw_word_t *wp = (unw_word_t *) env;
60d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  extern int _UI_siglongjmp_cont;
61d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  extern int _UI_longjmp_cont;
62d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  unw_context_t uc;
63d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  unw_cursor_t c;
64d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  unw_word_t sp;
65d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  int *cont;
66d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
67d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0)
68d9e100753f5694ebb14769048373e8171f336127hp.com!davidm    abort ();
69d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
70d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  do
71d9e100753f5694ebb14769048373e8171f336127hp.com!davidm    {
72d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0)
73d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	abort ();
745715d912f4f43041735031170d7f8ead6f70924dKonstantin Belousov#ifdef __FreeBSD__
755715d912f4f43041735031170d7f8ead6f70924dKonstantin Belousov      if (sp != wp[JB_SP] + sizeof(unw_word_t))
765715d912f4f43041735031170d7f8ead6f70924dKonstantin Belousov#else
77d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      if (sp != wp[JB_SP])
785715d912f4f43041735031170d7f8ead6f70924dKonstantin Belousov#endif
79d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	continue;
80d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
81d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      if (!bsp_match (&c, wp))
82d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	continue;
83d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
84d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      /* found the right frame: */
85d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
86d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      /* default to resuming without restoring signal-mask */
87d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      cont = &_UI_longjmp_cont;
88d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
89d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      /* Order of evaluation is important here: if unw_resume()
90d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	 restores signal mask, we must set it up appropriately, even
91d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	 if wp[JB_MASK_SAVED] is FALSE.  */
92d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      if (!resume_restores_sigmask (&c, wp) && wp[JB_MASK_SAVED])
93d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	{
94d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	  /* sigmask was saved */
9559328832f7ee48682fcd0fd1ca0cb9cfdb32ec4aKonstantin Belousov#if defined(__linux__)
9659328832f7ee48682fcd0fd1ca0cb9cfdb32ec4aKonstantin Belousov	  if (UNW_NUM_EH_REGS < 4 || _NSIG > 16 * sizeof (unw_word_t))
97d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	    /* signal mask doesn't fit into EH arguments and we can't
98d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	       put it on the stack without overwriting something
99d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	       else... */
100d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	    abort ();
101d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	  else
102d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	    if (unw_set_reg (&c, UNW_REG_EH + 2, wp[JB_MASK]) < 0
103d9e100753f5694ebb14769048373e8171f336127hp.com!davidm		|| (_NSIG > 8 * sizeof (unw_word_t)
104d9e100753f5694ebb14769048373e8171f336127hp.com!davidm		    && unw_set_reg (&c, UNW_REG_EH + 3, wp[JB_MASK + 1]) < 0))
105d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	      abort ();
10659328832f7ee48682fcd0fd1ca0cb9cfdb32ec4aKonstantin Belousov#elif defined(__FreeBSD__)
10759328832f7ee48682fcd0fd1ca0cb9cfdb32ec4aKonstantin Belousov	  if (unw_set_reg (&c, UNW_REG_EH + 2, &wp[JB_MASK]) < 0)
10859328832f7ee48682fcd0fd1ca0cb9cfdb32ec4aKonstantin Belousov	      abort();
10959328832f7ee48682fcd0fd1ca0cb9cfdb32ec4aKonstantin Belousov#else
11059328832f7ee48682fcd0fd1ca0cb9cfdb32ec4aKonstantin Belousov#error Port me
11159328832f7ee48682fcd0fd1ca0cb9cfdb32ec4aKonstantin Belousov#endif
112d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	  cont = &_UI_siglongjmp_cont;
113d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	}
114d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
115d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
116d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	  || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
1173842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz	  || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont))
118d9e100753f5694ebb14769048373e8171f336127hp.com!davidm	abort ();
119d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
120d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      unw_resume (&c);
121d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
122d9e100753f5694ebb14769048373e8171f336127hp.com!davidm      abort ();
123d9e100753f5694ebb14769048373e8171f336127hp.com!davidm    }
124297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov  while (unw_step (&c) > 0);
125d9e100753f5694ebb14769048373e8171f336127hp.com!davidm
126d9e100753f5694ebb14769048373e8171f336127hp.com!davidm  abort ();
127d9e100753f5694ebb14769048373e8171f336127hp.com!davidm}
128