Gos-freebsd.c revision 2c50c95cde4e2a7f69b7f14ff48934f34003aabd
1e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm/* libunwind - a platform-independent unwind library
2fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov   Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
3e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
4e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmThis file is part of libunwind.
5e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
6e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmPermission is hereby granted, free of charge, to any person obtaining
7e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidma copy of this software and associated documentation files (the
8e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm"Software"), to deal in the Software without restriction, including
9e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmwithout limitation the rights to use, copy, modify, merge, publish,
10e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmdistribute, sublicense, and/or sell copies of the Software, and to
11e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmpermit persons to whom the Software is furnished to do so, subject to
12e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmthe following conditions:
13e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
14e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmThe above copyright notice and this permission notice shall be
15e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmincluded in all copies or substantial portions of the Software.
16e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
17e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
24e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
25fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#ifdef HAVE_CONFIG_H
26fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include "config.h"
27fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#endif
28fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
29fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include <sys/types.h>
30fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include <signal.h>
31fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include <ucontext.h>
32fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include <machine/sigframe.h>
33fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
34e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm#include "unwind_i.h"
35fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include "offsets.h"
36e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
37e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmPROTECTED int
38e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmunw_is_signal_frame (unw_cursor_t *cursor)
39e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm{
40a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  struct cursor *c = (struct cursor *) cursor;
41a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_word_t w0, w1, w2, w3, w4, w5, ip;
42a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_addr_space_t as;
43a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_accessors_t *a;
44a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  void *arg;
45a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  int ret;
46a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
47a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  as = c->dwarf.as;
48a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  a = unw_get_accessors (as);
49a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  arg = c->dwarf.as_arg;
50a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
51a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  /* Check if EIP points at sigreturn() sequence.  It can be:
528a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovsigcode+4: from amd64 freebsd32 environment
538a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov8d 44 24 20		lea    0x20(%esp),%eax
548a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov50			push   %eax
558a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovb8 a1 01 00 00		mov    $0x1a1,%ea
568a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov50			push   %eax
578a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovcd 80			int    $0x80
588a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov
598a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovsigcode+4: from real i386
60a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov8d 44 24 20		lea    0x20(%esp),%eax
61a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov50			push   %eax
62a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovf7 40 54 00 02 00	testl  $0x20000,0x54(%eax)
63a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov75 03			jne    sigcode+21
64a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov8e 68 14		mov    0x14(%eax),%gs
65a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovb8 a1 01 00 00		mov    $0x1a1,%eax
66a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov50			push   %eax
67a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovcd 80			int    $0x80
68a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
69a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovfreebsd4_sigcode+4:
70a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin BelousovXXX
71a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovosigcode:
72a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin BelousovXXX
73a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  */
74a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  ip = c->dwarf.ip;
75e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  ret = X86_SCF_NONE;
76fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  c->sigcontext_format = ret;
778a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 ||
788a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 ||
798a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 ||
808a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 12, &w3, 0, arg) < 0)
818a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    return ret;
828a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  if (w0 == 0x2024448d && w1 == 0x01a1b850 && w2 == 0xcd500000 &&
838a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (w3 & 0xff) == 0x80)
84e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov    ret = X86_SCF_FREEBSD_SIGFRAME;
858a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  else {
868a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    if ((*a->access_mem) (as, ip + 16, &w4, 0, arg) < 0 ||
878a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov	(*a->access_mem) (as, ip + 20, &w5, 0, arg) < 0)
888a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      return ret;
898a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 &&
908a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov	w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000)
918a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      ret = X86_SCF_FREEBSD_SIGFRAME;
928a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  }
93a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  Debug (16, "returning %d\n", ret);
94fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  c->sigcontext_format = ret;
95e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  return (ret);
96fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov}
97fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
98fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin BelousovPROTECTED int
99fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousovunw_handle_signal_frame (unw_cursor_t *cursor)
100fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov{
101fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  struct cursor *c = (struct cursor *) cursor;
102fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  int ret;
103fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
104fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) {
105fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    struct sigframe *sf;
106fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    uintptr_t uc_addr;
107fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    struct dwarf_loc esp_loc;
108fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
109fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    sf = (struct sigframe *)c->dwarf.cfa;
110fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    uc_addr = (uintptr_t)&(sf->sf_uc);
111fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
112fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
113fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
114fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    if (ret < 0)
115fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    {
116fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov	    Debug (2, "returning 0\n");
117fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov	    return 0;
118fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    }
119fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
120fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EIP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0);
121fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
122fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EAX_OFF, 0);
123fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ECX_OFF, 0);
124fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDX_OFF, 0);
125fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBX_OFF, 0);
126fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0);
127fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESI_OFF, 0);
128fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDI_OFF, 0);
129fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0);
130fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_TRAPNO_OFF, 0);
131fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[ST0] = DWARF_NULL_LOC;
132fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  } else {
133fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    Debug (8, "Gstep: not handling frame format %d\n", c->sigcontext_format);
134fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    abort();
135fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  }
136fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  return 0;
137e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm}
13879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
13979d012348df333f191fcb10789dad12b655f2baaKonstantin BelousovHIDDEN dwarf_loc_t
14079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousovx86_get_scratch_loc (struct cursor *c, unw_regnum_t reg)
14179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov{
14279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  unw_word_t addr = c->sigcontext_addr, fpstate_addr, off;
14379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  int ret, is_fpstate = 0;
14479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
14579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  switch (c->sigcontext_format)
14679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    {
14779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_NONE:
14879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      return DWARF_REG_LOC (&c->dwarf, reg);
14979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
15079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_FREEBSD_SIGFRAME:
15179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      addr += FREEBSD_UC_MCONTEXT_OFF;
15279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
15379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
15479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_FREEBSD_SIGFRAME4:
15579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      abort();
15679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
15779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
15879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_FREEBSD_OSIGFRAME:
15979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      /* XXXKIB */
16079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      abort();
16179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
16279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
16379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_FREEBSD_SYSCALL:
16479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      /* XXXKIB */
16579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      abort();
16679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
16779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
16879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    default:
16979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      /* XXXKIB */
17079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      abort();
17179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
17279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    }
17379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
17479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  switch (reg)
17579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    {
17679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break;
17779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FS: off = FREEBSD_UC_MCONTEXT_FS_OFF; break;
17879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ES: off = FREEBSD_UC_MCONTEXT_ES_OFF; break;
17979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_DS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;
18079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EDI: off = FREEBSD_UC_MCONTEXT_EDI_OFF; break;
18179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ESI: off = FREEBSD_UC_MCONTEXT_ESI_OFF; break;
18279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EBP: off = FREEBSD_UC_MCONTEXT_EBP_OFF; break;
18379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ESP: off = FREEBSD_UC_MCONTEXT_ESP_OFF; break;
18479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EBX: off = FREEBSD_UC_MCONTEXT_EBX_OFF; break;
18579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EDX: off = FREEBSD_UC_MCONTEXT_EDX_OFF; break;
18679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ECX: off = FREEBSD_UC_MCONTEXT_ECX_OFF; break;
18779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EAX: off = FREEBSD_UC_MCONTEXT_EAX_OFF; break;
18879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_TRAPNO: off = FREEBSD_UC_MCONTEXT_TRAPNO_OFF; break;
18979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EIP: off = FREEBSD_UC_MCONTEXT_EIP_OFF; break;
19079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_CS: off = FREEBSD_UC_MCONTEXT_CS_OFF; break;
19179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break;
19279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;
19379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
19479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    /* XXXKIB fix */
19579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break;
19679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break;
19779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break;
19879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break;
19979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break;
20079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break;
20179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break;
20279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break;
20379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
20479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      /* stacked fp registers */
20579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3:
20679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7:
20779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      is_fpstate = 1;
20879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0);
20979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
21079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
21179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov     /* SSE fp registers */
21279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi:
21379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi:
21479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi:
21579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi:
21679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi:
21779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi:
21879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi:
21979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi:
22079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      is_fpstate = 1;
22179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo);
22279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
22379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM0:
22479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM1:
22579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM2:
22679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM3:
22779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM4:
22879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM5:
22979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM6:
23079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM7:
23179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      is_fpstate = 1;
23279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0);
23379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
23479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
23579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FOP:
23679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_TSS:
23779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_LDT:
23879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    default:
23979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      return DWARF_REG_LOC (&c->dwarf, reg);
24079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    }
24179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
24279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  if (is_fpstate)
24379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    {
24479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      if ((ret = dwarf_get (&c->dwarf,
24579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov			    DWARF_MEM_LOC (&c->dwarf,
24679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov					   addr + LINUX_SC_FPSTATE_OFF),
24779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov			    &fpstate_addr)) < 0)
24879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov	return DWARF_NULL_LOC;
24979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
25079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      if (!fpstate_addr)
25179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov	return DWARF_NULL_LOC;
25279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
25379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      return DWARF_MEM_LOC (c, fpstate_addr + off);
25479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    }
25579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  else
25679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    return DWARF_MEM_LOC (c, addr + off);
25779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov}
2580dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov
2590dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov#ifndef UNW_REMOTE_ONLY
2600dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin BelousovHIDDEN void *
2610dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousovx86_r_uc_addr (ucontext_t *uc, int reg)
2620dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov{
2630dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  void *addr;
2640dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov
2650dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  switch (reg)
2660dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    {
2670dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_GS:  addr = &uc->uc_mcontext.mc_gs; break;
2680dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_FS:  addr = &uc->uc_mcontext.mc_fs; break;
2690dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_ES:  addr = &uc->uc_mcontext.mc_es; break;
2700dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_DS:  addr = &uc->uc_mcontext.mc_ds; break;
2710dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EAX: addr = &uc->uc_mcontext.mc_eax; break;
2720dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EBX: addr = &uc->uc_mcontext.mc_ebx; break;
2730dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_ECX: addr = &uc->uc_mcontext.mc_ecx; break;
2740dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EDX: addr = &uc->uc_mcontext.mc_edx; break;
2750dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_ESI: addr = &uc->uc_mcontext.mc_esi; break;
2760dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EDI: addr = &uc->uc_mcontext.mc_edi; break;
2770dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EBP: addr = &uc->uc_mcontext.mc_ebp; break;
2780dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EIP: addr = &uc->uc_mcontext.mc_eip; break;
2790dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_ESP: addr = &uc->uc_mcontext.mc_esp; break;
2800dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_TRAPNO:  addr = &uc->uc_mcontext.mc_trapno; break;
2810dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_CS:  addr = &uc->uc_mcontext.mc_cs; break;
2820dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EFLAGS:  addr = &uc->uc_mcontext.mc_eflags; break;
2830dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_SS:  addr = &uc->uc_mcontext.mc_ss; break;
2840dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov
2850dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    default:
2860dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov      addr = NULL;
2870dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    }
2880dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  return addr;
2890dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov}
290979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
291979af4502fe19b0d98459633731d004a4a010a0eKonstantin BelousovHIDDEN int
292979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousovx86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
293979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov{
294979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  struct cursor *c = (struct cursor *) cursor;
295979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  ucontext_t *uc = c->uc;
296979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
297979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  /* Ensure c->pi is up-to-date.  On x86, it's relatively common to be
298979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov     missing DWARF unwind info.  We don't want to fail in that case,
299979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov     because the frame-chain still would let us do a backtrace at
300979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov     least.  */
301979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  dwarf_make_proc_info (&c->dwarf);
302979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
303979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  if (c->sigcontext_format == X86_SCF_NONE) {
304979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip);
305979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      setcontext (uc);
306979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  } else if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) {
307979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
308979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
309979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc);
3102c50c95cde4e2a7f69b7f14ff48934f34003aabdKonstantin Belousov      sigreturn((ucontext_t *)((const char *)sc + FREEBSD_UC_MCONTEXT_OFF));
311979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  } else {
312979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n",
3132c50c95cde4e2a7f69b7f14ff48934f34003aabdKonstantin Belousov      c->dwarf.ip, c->sigcontext_format);
314979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      abort();
315979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  }
316979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  return -UNW_EINVAL;
317979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov}
318979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
3190dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov#endif
320