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