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