Gos-freebsd.c revision 8a75ba971a295ce7e6b7b73b90272fb9c04e5b2f
1e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm/* libunwind - a platform-independent unwind library
2e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm   Copyright (C) 2002-2003 Hewlett-Packard Co
3e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
5e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmThis file is part of libunwind.
6e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
7e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmPermission is hereby granted, free of charge, to any person obtaining
8e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidma copy of this software and associated documentation files (the
9e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm"Software"), to deal in the Software without restriction, including
10e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmwithout limitation the rights to use, copy, modify, merge, publish,
11e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmdistribute, sublicense, and/or sell copies of the Software, and to
12e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmpermit persons to whom the Software is furnished to do so, subject to
13e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmthe following conditions:
14e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
15e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmThe above copyright notice and this permission notice shall be
16e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmincluded in all copies or substantial portions of the Software.
17e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
18e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
26e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm#include "unwind_i.h"
27e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
28e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmPROTECTED int
29e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmunw_is_signal_frame (unw_cursor_t *cursor)
30e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm{
31a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov#if defined __linux__
32e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  struct cursor *c = (struct cursor *) cursor;
33e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  unw_word_t w0, w1, ip;
34e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  unw_addr_space_t as;
35e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  unw_accessors_t *a;
36e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  void *arg;
37e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  int ret;
38e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
39e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  as = c->dwarf.as;
40e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  a = unw_get_accessors (as);
41e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  arg = c->dwarf.as_arg;
42e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
43e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  /* Check if EIP points at sigreturn() sequence.  On Linux, this is:
44e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
45e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm    __restore:
46e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm	0x58				pop %eax
47e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm	0xb8 0x77 0x00 0x00 0x00	movl 0x77,%eax
48e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm	0xcd 0x80			int 0x80
49e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
50e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm     without SA_SIGINFO, and
51e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
52e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm    __restore_rt:
53e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm       0xb8 0xad 0x00 0x00 0x00        movl 0x80,%eax
54e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm       0xcd 0x80                       int 0x80
55e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm       0x90                            nop
56e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
57e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm     if SA_SIGINFO is specified.
58e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  */
59e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  ip = c->dwarf.ip;
60e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
61e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm      || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0)
62e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov     return ret;
63e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  ret = X86_SCF_NONE;
64e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  if (w0 == 0x0077b858 && w1 == 0x80cd0000)
65e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov     ret = X86_SCF_LINUX_SIGFRAME;
66e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  else if (w0 == 0x0000adb8 && w1 == 0x9080cd00)
67e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov     ret = X86_SCF_LINUX_RT_SIGFRAME;
68e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  Debug (16, "returning %d\n", ret);
69e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  return ret;
70a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov#elif defined __FreeBSD__
71a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  struct cursor *c = (struct cursor *) cursor;
72a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_word_t w0, w1, w2, w3, w4, w5, ip;
73a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_addr_space_t as;
74a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_accessors_t *a;
75a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  void *arg;
76a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  int ret;
77a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
78a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  as = c->dwarf.as;
79a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  a = unw_get_accessors (as);
80a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  arg = c->dwarf.as_arg;
81a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
82a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  /* Check if EIP points at sigreturn() sequence.  It can be:
838a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovsigcode+4: from amd64 freebsd32 environment
848a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov8d 44 24 20		lea    0x20(%esp),%eax
858a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov50			push   %eax
868a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovb8 a1 01 00 00		mov    $0x1a1,%ea
878a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov50			push   %eax
888a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovcd 80			int    $0x80
898a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov
908a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovsigcode+4: from real i386
91a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov8d 44 24 20		lea    0x20(%esp),%eax
92a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov50			push   %eax
93a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovf7 40 54 00 02 00	testl  $0x20000,0x54(%eax)
94a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov75 03			jne    sigcode+21
95a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov8e 68 14		mov    0x14(%eax),%gs
96a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovb8 a1 01 00 00		mov    $0x1a1,%eax
97a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov50			push   %eax
98a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovcd 80			int    $0x80
99a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
100a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovfreebsd4_sigcode+4:
101a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin BelousovXXX
102a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovosigcode:
103a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin BelousovXXX
104a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  */
105a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  ip = c->dwarf.ip;
106e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  ret = X86_SCF_NONE;
1078a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 ||
1088a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 ||
1098a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 ||
1108a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 12, &w3, 0, arg) < 0)
1118a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    return ret;
1128a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  if (w0 == 0x2024448d && w1 == 0x01a1b850 && w2 == 0xcd500000 &&
1138a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (w3 & 0xff) == 0x80)
114e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov    ret = X86_SCF_FREEBSD_SIGFRAME;
1158a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  else {
1168a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    if ((*a->access_mem) (as, ip + 16, &w4, 0, arg) < 0 ||
1178a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov	(*a->access_mem) (as, ip + 20, &w5, 0, arg) < 0)
1188a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      return ret;
1198a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 &&
1208a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov	w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000)
1218a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      ret = X86_SCF_FREEBSD_SIGFRAME;
1228a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  }
123a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  Debug (16, "returning %d\n", ret);
124e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  return (ret);
125e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm#else
126a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov#error Port me
127e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm#endif
128e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm  return -UNW_ENOINFO;
129e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm}
130