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>
3121f0e90ce85da99c2897d5e2163e8183436becdcKonstantin Belousov#include <stddef.h>
32fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include <ucontext.h>
33fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include <machine/sigframe.h>
34fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
35e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm#include "unwind_i.h"
36fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov#include "offsets.h"
37e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm
38e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmPROTECTED int
39e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidmunw_is_signal_frame (unw_cursor_t *cursor)
40e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm{
41a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  struct cursor *c = (struct cursor *) cursor;
42a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_word_t w0, w1, w2, w3, w4, w5, ip;
43a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_addr_space_t as;
44a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  unw_accessors_t *a;
45a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  void *arg;
46a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  int ret;
47a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
48a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  as = c->dwarf.as;
49a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  a = unw_get_accessors (as);
50a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  arg = c->dwarf.as_arg;
51a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
52a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  /* Check if EIP points at sigreturn() sequence.  It can be:
538a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovsigcode+4: from amd64 freebsd32 environment
548a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov8d 44 24 20		lea    0x20(%esp),%eax
558a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov50			push   %eax
5634b064bf2233ec8c9223786f4bc714585bbce4f7Konstantin Belousovb8 a1 01 00 00		mov    $0x1a1,%eax
578a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov50			push   %eax
588a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovcd 80			int    $0x80
598a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov
608a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousovsigcode+4: from real i386
61a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov8d 44 24 20		lea    0x20(%esp),%eax
62a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov50			push   %eax
63a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovf7 40 54 00 02 00	testl  $0x20000,0x54(%eax)
64a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov75 03			jne    sigcode+21
65a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov8e 68 14		mov    0x14(%eax),%gs
66a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovb8 a1 01 00 00		mov    $0x1a1,%eax
67a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov50			push   %eax
68a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovcd 80			int    $0x80
69a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov
70a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovfreebsd4_sigcode+4:
71a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin BelousovXXX
72a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousovosigcode:
73a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin BelousovXXX
74a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  */
75a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  ip = c->dwarf.ip;
76e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  ret = X86_SCF_NONE;
77fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  c->sigcontext_format = ret;
788a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 ||
798a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 ||
808a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 ||
818a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (*a->access_mem) (as, ip + 12, &w3, 0, arg) < 0)
828a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    return ret;
838a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  if (w0 == 0x2024448d && w1 == 0x01a1b850 && w2 == 0xcd500000 &&
848a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      (w3 & 0xff) == 0x80)
85e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov    ret = X86_SCF_FREEBSD_SIGFRAME;
868a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  else {
878a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    if ((*a->access_mem) (as, ip + 16, &w4, 0, arg) < 0 ||
888a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov	(*a->access_mem) (as, ip + 20, &w5, 0, arg) < 0)
898a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      return ret;
908a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov    if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 &&
918a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov	w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000)
928a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov      ret = X86_SCF_FREEBSD_SIGFRAME;
938a75ba971a295ce7e6b7b73b90272fb9c04e5b2fKonstantin Belousov  }
94a6b23dcb0c42198ad01764a27a084fd49116a544Konstantin Belousov  Debug (16, "returning %d\n", ret);
95fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  c->sigcontext_format = ret;
96e9cd30040e2794ee586ff853b360b47881824fdaKonstantin Belousov  return (ret);
97fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov}
98fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
99fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin BelousovPROTECTED int
100fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousovunw_handle_signal_frame (unw_cursor_t *cursor)
101fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov{
102fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  struct cursor *c = (struct cursor *) cursor;
103fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  int ret;
104fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
105fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) {
106fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    struct sigframe *sf;
107fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    uintptr_t uc_addr;
108fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    struct dwarf_loc esp_loc;
109fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
110fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    sf = (struct sigframe *)c->dwarf.cfa;
111fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    uc_addr = (uintptr_t)&(sf->sf_uc);
11221f0e90ce85da99c2897d5e2163e8183436becdcKonstantin Belousov    c->sigcontext_addr = c->dwarf.cfa;
113fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
114fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
115fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa);
116fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    if (ret < 0)
117fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    {
118fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov	    Debug (2, "returning 0\n");
119fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov	    return 0;
120fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    }
121fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov
122fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EIP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0);
123fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0);
124fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EAX_OFF, 0);
125fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ECX_OFF, 0);
126fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDX_OFF, 0);
127fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBX_OFF, 0);
128fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0);
129fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESI_OFF, 0);
130fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDI_OFF, 0);
131fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0);
132fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_TRAPNO_OFF, 0);
133fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    c->dwarf.loc[ST0] = DWARF_NULL_LOC;
134fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  } else {
135fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    Debug (8, "Gstep: not handling frame format %d\n", c->sigcontext_format);
136fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov    abort();
137fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  }
138fd88f418184b82ea5dc191e16ae9f3705c865f68Konstantin Belousov  return 0;
139e1eb2d465605ac4eae98dd4f8264de4c6d56aab4homeip.net!davidm}
14079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
14179d012348df333f191fcb10789dad12b655f2baaKonstantin BelousovHIDDEN dwarf_loc_t
14279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousovx86_get_scratch_loc (struct cursor *c, unw_regnum_t reg)
14379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov{
144f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov  unw_word_t addr = c->sigcontext_addr, off, xmm_off;
145f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov  unw_word_t fpstate, fpformat;
146f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov  int ret, is_fpstate = 0, is_xmmstate = 0;
14779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
14879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  switch (c->sigcontext_format)
14979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    {
15079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_NONE:
15179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      return DWARF_REG_LOC (&c->dwarf, reg);
15279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
15379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_FREEBSD_SIGFRAME:
15421f0e90ce85da99c2897d5e2163e8183436becdcKonstantin Belousov      addr += offsetof(struct sigframe, sf_uc) + FREEBSD_UC_MCONTEXT_OFF;
15579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
15679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
15779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_FREEBSD_SIGFRAME4:
15879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      abort();
15979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
16079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
16179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_FREEBSD_OSIGFRAME:
16279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      /* XXXKIB */
16379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      abort();
16479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
16579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
16679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case X86_SCF_FREEBSD_SYSCALL:
16779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      /* XXXKIB */
16879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      abort();
16979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
17079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
17179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    default:
17279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      /* XXXKIB */
17379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      abort();
17479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
17579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    }
17679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
177f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov  off = 0; /* shut gcc warning */
17879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  switch (reg)
17979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    {
18079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break;
18179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FS: off = FREEBSD_UC_MCONTEXT_FS_OFF; break;
18279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ES: off = FREEBSD_UC_MCONTEXT_ES_OFF; break;
18379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_DS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;
18479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EDI: off = FREEBSD_UC_MCONTEXT_EDI_OFF; break;
18579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ESI: off = FREEBSD_UC_MCONTEXT_ESI_OFF; break;
18679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EBP: off = FREEBSD_UC_MCONTEXT_EBP_OFF; break;
18779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ESP: off = FREEBSD_UC_MCONTEXT_ESP_OFF; break;
18879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EBX: off = FREEBSD_UC_MCONTEXT_EBX_OFF; break;
18979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EDX: off = FREEBSD_UC_MCONTEXT_EDX_OFF; break;
19079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ECX: off = FREEBSD_UC_MCONTEXT_ECX_OFF; break;
19179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EAX: off = FREEBSD_UC_MCONTEXT_EAX_OFF; break;
19279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_TRAPNO: off = FREEBSD_UC_MCONTEXT_TRAPNO_OFF; break;
19379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EIP: off = FREEBSD_UC_MCONTEXT_EIP_OFF; break;
19479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_CS: off = FREEBSD_UC_MCONTEXT_CS_OFF; break;
19579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break;
19679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break;
19779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
198f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov    case UNW_X86_FCW:
199f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_fpstate = 1;
200f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      off = FREEBSD_UC_MCONTEXT_CW_OFF;
201f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_CW_XMM_OFF;
202f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      break;
203f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov    case UNW_X86_FSW:
204f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_fpstate = 1;
205f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      off = FREEBSD_UC_MCONTEXT_SW_OFF;
206f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_SW_XMM_OFF;
207f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      break;
208f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov    case UNW_X86_FTW:
209f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_fpstate = 1;
210f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_TAG_XMM_OFF;
211f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      off = FREEBSD_UC_MCONTEXT_TAG_OFF;
212f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      break;
213f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov    case UNW_X86_FCS:
214f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_fpstate = 1;
215f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      off = FREEBSD_UC_MCONTEXT_CSSEL_OFF;
216f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF;
217f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      break;
218f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov    case UNW_X86_FIP:
219f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_fpstate = 1;
220f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      off = FREEBSD_UC_MCONTEXT_IPOFF_OFF;
221f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF;
222f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      break;
223f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov    case UNW_X86_FEA:
224f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_fpstate = 1;
225f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      off = FREEBSD_UC_MCONTEXT_DATAOFF_OFF;
226f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF;
227f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      break;
228f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov    case UNW_X86_FDS:
229f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_fpstate = 1;
230f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      off = FREEBSD_US_MCONTEXT_DATASEL_OFF;
231f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF;
232f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      break;
233f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov    case UNW_X86_MXCSR:
234f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_fpstate = 1;
235dd1c7b6c1a4fc4c6f833b3f3ef21cde1eebcf03bKonstantin Belousov      is_xmmstate = 1;
236f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF;
237f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      break;
23879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
23979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      /* stacked fp registers */
24079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3:
24179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7:
24279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      is_fpstate = 1;
243f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      off = FREEBSD_UC_MCONTEXT_ST0_OFF + 10*(reg - UNW_X86_ST0);
244f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_ST0_XMM_OFF + 10*(reg - UNW_X86_ST0);
24579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
24679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
24779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov     /* SSE fp registers */
24879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi:
24979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi:
25079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi:
25179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi:
25279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi:
25379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi:
25479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi:
25579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi:
25679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      is_fpstate = 1;
257f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_xmmstate = 1;
258f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo);
25979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
26079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM0:
26179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM1:
26279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM2:
26379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM3:
26479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM4:
26579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM5:
26679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM6:
26779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_XMM7:
26879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      is_fpstate = 1;
269f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      is_xmmstate = 1;
270f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 16*(reg - UNW_X86_XMM0);
27179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      break;
27279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
27379d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_FOP:
27479d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_TSS:
27579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    case UNW_X86_LDT:
27679d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    default:
27779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      return DWARF_REG_LOC (&c->dwarf, reg);
27879d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    }
27979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov
28079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov  if (is_fpstate)
28179d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    {
28279d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov      if ((ret = dwarf_get (&c->dwarf,
283f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov	   DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPSTATE_OFF),
284f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov	   &fpstate)) < 0)
28579d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov	return DWARF_NULL_LOC;
286f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      if (fpstate == FREEBSD_UC_MCONTEXT_FPOWNED_NONE)
28779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov	return DWARF_NULL_LOC;
288f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      if ((ret = dwarf_get (&c->dwarf,
289f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov	   DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPFORMAT_OFF),
290f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov	   &fpformat)) < 0)
291f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov	return DWARF_NULL_LOC;
292f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      if (fpformat == FREEBSD_UC_MCONTEXT_FPFMT_NODEV ||
293f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov	  (is_xmmstate && fpformat != FREEBSD_UC_MCONTEXT_FPFMT_XMM))
294f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov	return DWARF_NULL_LOC;
295f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov      if (is_xmmstate)
296f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov	off = xmm_off;
29779d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    }
298f6546e27ed70661c1b148521e15c539559ee4e25Konstantin Belousov
29979d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov    return DWARF_MEM_LOC (c, addr + off);
30079d012348df333f191fcb10789dad12b655f2baaKonstantin Belousov}
3010dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov
3020dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov#ifndef UNW_REMOTE_ONLY
3030dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin BelousovHIDDEN void *
3040dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousovx86_r_uc_addr (ucontext_t *uc, int reg)
3050dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov{
3060dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  void *addr;
3070dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov
3080dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  switch (reg)
3090dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    {
3100dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_GS:  addr = &uc->uc_mcontext.mc_gs; break;
3110dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_FS:  addr = &uc->uc_mcontext.mc_fs; break;
3120dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_ES:  addr = &uc->uc_mcontext.mc_es; break;
3130dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_DS:  addr = &uc->uc_mcontext.mc_ds; break;
3140dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EAX: addr = &uc->uc_mcontext.mc_eax; break;
3150dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EBX: addr = &uc->uc_mcontext.mc_ebx; break;
3160dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_ECX: addr = &uc->uc_mcontext.mc_ecx; break;
3170dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EDX: addr = &uc->uc_mcontext.mc_edx; break;
3180dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_ESI: addr = &uc->uc_mcontext.mc_esi; break;
3190dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EDI: addr = &uc->uc_mcontext.mc_edi; break;
3200dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EBP: addr = &uc->uc_mcontext.mc_ebp; break;
3210dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EIP: addr = &uc->uc_mcontext.mc_eip; break;
3220dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_ESP: addr = &uc->uc_mcontext.mc_esp; break;
3230dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_TRAPNO:  addr = &uc->uc_mcontext.mc_trapno; break;
3240dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_CS:  addr = &uc->uc_mcontext.mc_cs; break;
3250dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_EFLAGS:  addr = &uc->uc_mcontext.mc_eflags; break;
3260dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    case UNW_X86_SS:  addr = &uc->uc_mcontext.mc_ss; break;
3270dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov
3280dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    default:
3290dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov      addr = NULL;
3300dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov    }
3310dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov  return addr;
3320dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov}
333979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
334979af4502fe19b0d98459633731d004a4a010a0eKonstantin BelousovHIDDEN int
335979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousovx86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
336979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov{
337979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  struct cursor *c = (struct cursor *) cursor;
338979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  ucontext_t *uc = c->uc;
339979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
340979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  /* Ensure c->pi is up-to-date.  On x86, it's relatively common to be
341979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov     missing DWARF unwind info.  We don't want to fail in that case,
342979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov     because the frame-chain still would let us do a backtrace at
343979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov     least.  */
344979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  dwarf_make_proc_info (&c->dwarf);
345979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
346979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  if (c->sigcontext_format == X86_SCF_NONE) {
347979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip);
348979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      setcontext (uc);
3490d311ea1617fd0ebff52dfacc85746fcc165bb10Konstantin Belousov      abort();
350979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  } else if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) {
351979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
352979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
353979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc);
354127acf8e97047f0c5faf31114b1fea370c0c6389Konstantin Belousov      sigreturn((ucontext_t *)((const char *)sc + FREEBSD_SC_UCONTEXT_OFF));
3550d311ea1617fd0ebff52dfacc85746fcc165bb10Konstantin Belousov      abort();
356979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  } else {
357979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n",
3582c50c95cde4e2a7f69b7f14ff48934f34003aabdKonstantin Belousov      c->dwarf.ip, c->sigcontext_format);
359979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov      abort();
360979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  }
361979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov  return -UNW_EINVAL;
362979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov}
363979af4502fe19b0d98459633731d004a4a010a0eKonstantin Belousov
3640dbeeeb08dc9a7e46281954e9225a84d4629a3dbKonstantin Belousov#endif
365