1a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang/* libunwind - a platform-independent unwind library
2a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang   Copyright (C) 2003-2004 Hewlett-Packard Co
3a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
5a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangThis file is part of libunwind.
6a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
7a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangPermission is hereby granted, free of charge, to any person obtaining
8a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tanga copy of this software and associated documentation files (the
9a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang"Software"), to deal in the Software without restriction, including
10a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tangwithout limitation the rights to use, copy, modify, merge, publish,
11a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tangdistribute, sublicense, and/or sell copies of the Software, and to
12a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tangpermit persons to whom the Software is furnished to do so, subject to
13a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tangthe following conditions:
14a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
15a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangThe above copyright notice and this permission notice shall be
16a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tangincluded in all copies or substantial portions of the Software.
17a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
18a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-TangWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
26a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#define UNW_LOCAL_ONLY
27a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
28c4133e879b8cfa7e7295f7d35bde22dfc800ebc8Arun Sharma#undef _FORTIFY_SOURCE
29a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#include <assert.h>
30a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#include <libunwind.h>
31a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#include <setjmp.h>
32a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#include <signal.h>
33a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#include <stdlib.h>
34a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
35a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#include "jmpbuf.h"
36a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#include "setjmp_i.h"
37a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
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 longjmp here.  */
502b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#define _longjmp __nonworking__longjmp
512b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#define longjmp __nonworking_longjmp
522b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousovstatic void _longjmp (jmp_buf env, int val);
532b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousovstatic void longjmp (jmp_buf env, int val);
542b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#endif
552b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#endif /* __GLIBC__ */
56297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov
57a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tangvoid
58a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang_longjmp (jmp_buf env, int val)
59a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang{
60a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  extern int _UI_longjmp_cont;
61a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  unw_context_t uc;
62a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  unw_cursor_t c;
63a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  unw_word_t sp;
64a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  unw_word_t *wp = (unw_word_t *) env;
65a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
66a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0)
67a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang    abort ();
68a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
69a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  do
70a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang    {
71a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang      if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0)
72a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang	abort ();
735715d912f4f43041735031170d7f8ead6f70924dKonstantin Belousov#ifdef __FreeBSD__
745715d912f4f43041735031170d7f8ead6f70924dKonstantin Belousov      if (sp != wp[JB_SP] + sizeof(unw_word_t))
755715d912f4f43041735031170d7f8ead6f70924dKonstantin Belousov#else
76a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang      if (sp != wp[JB_SP])
775715d912f4f43041735031170d7f8ead6f70924dKonstantin Belousov#endif
78a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang	continue;
79a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
80a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang      if (!bsp_match (&c, wp))
81a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang	continue;
82a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
83a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang      /* found the right frame: */
84a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
85a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang      assert (UNW_NUM_EH_REGS >= 2);
86a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
87a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang      if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0
88a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang	  || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0
89a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang	  || unw_set_reg (&c, UNW_REG_IP,
903842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz			  (unw_word_t) (uintptr_t) &_UI_longjmp_cont))
91a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang	abort ();
92a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
93a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang      unw_resume (&c);
94a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
95a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang      abort ();
96a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang    }
97297d9cd07d7ea9b541fb13bffe418c8b2a8c3aa6Paul Pluzhnikov  while (unw_step (&c) > 0);
98a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
99a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  abort ();
100a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang}
101a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
102a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#ifdef __GNUC__
1032b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#define STRINGIFY1(x) #x
1042b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#define STRINGIFY(x) STRINGIFY1(x)
1052b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousovvoid longjmp (jmp_buf env, int val)
1062b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov  __attribute__ ((alias (STRINGIFY(_longjmp))));
107a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang#else
108a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
109a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tangvoid
110a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tanglongjmp (jmp_buf env, int val)
111a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang{
112a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang  _longjmp (env, val);
113a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang}
114a369768c279654ae247643f81e0d2f6f7ddd4d15David Mosberger-Tang
1152b606faa21024932f6819ba31e846d866db9d2f9Konstantin Belousov#endif /* __GNUC__ */
116