1169689Skan/* DWARF2 EH unwinding support for IA64 Linux. 2169689Skan Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3169689Skan 4169689Skan This file is part of GCC. 5169689Skan 6169689Skan GCC is free software; you can redistribute it and/or modify it 7169689Skan under the terms of the GNU General Public License as published 8169689Skan by the Free Software Foundation; either version 2, or (at your 9169689Skan option) any later version. 10169689Skan 11169689Skan In addition to the permissions in the GNU General Public License, 12169689Skan the Free Software Foundation gives you unlimited permission to link 13169689Skan the compiled version of this file with other programs, and to 14169689Skan distribute those programs without any restriction coming from the 15169689Skan use of this file. (The General Public License restrictions do 16169689Skan apply in other respects; for example, they cover modification of 17169689Skan the file, and distribution when not linked into another program.) 18169689Skan 19169689Skan GCC is distributed in the hope that it will be useful, but WITHOUT 20169689Skan ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 21169689Skan or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22169689Skan License for more details. 23169689Skan 24169689Skan You should have received a copy of the GNU General Public License 25169689Skan along with GCC; see the file COPYING. If not, write to the 26169689Skan Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 27169689Skan MA 02110-1301, USA. */ 28169689Skan 29169689Skan/* Do code reading to identify a signal frame, and set the frame 30169689Skan state data appropriately. See unwind-dw2.c for the structs. */ 31169689Skan 32169689Skan/* This works only for glibc-2.3 and later, because sigcontext is different 33169689Skan in glibc-2.2.4. */ 34169689Skan 35169689Skan#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) 36169689Skan#include <signal.h> 37169689Skan#include <sys/ucontext.h> 38169689Skan 39169689Skan#define IA64_GATE_AREA_START 0xa000000000000100LL 40169689Skan#define IA64_GATE_AREA_END 0xa000000000030000LL 41169689Skan 42169689Skan#define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state 43169689Skan 44169689Skanstatic _Unwind_Reason_Code 45169689Skania64_fallback_frame_state (struct _Unwind_Context *context, 46169689Skan _Unwind_FrameState *fs) 47169689Skan{ 48169689Skan if (context->rp >= IA64_GATE_AREA_START 49169689Skan && context->rp < IA64_GATE_AREA_END) 50169689Skan { 51169689Skan struct sigframe { 52169689Skan char scratch[16]; 53169689Skan unsigned long sig_number; 54169689Skan struct siginfo *info; 55169689Skan struct sigcontext *sc; 56169689Skan } *frame_ = (struct sigframe *)context->psp; 57169689Skan struct sigcontext *sc = frame_->sc; 58169689Skan 59169689Skan /* Restore scratch registers in case the unwinder needs to 60169689Skan refer to a value stored in one of them. */ 61169689Skan { 62169689Skan int i; 63169689Skan 64169689Skan for (i = 2; i < 4; i++) 65169689Skan context->ireg[i - 2].loc = &sc->sc_gr[i]; 66169689Skan for (i = 8; i < 12; i++) 67169689Skan context->ireg[i - 2].loc = &sc->sc_gr[i]; 68169689Skan for (i = 14; i < 32; i++) 69169689Skan context->ireg[i - 2].loc = &sc->sc_gr[i]; 70169689Skan } 71169689Skan 72169689Skan context->fpsr_loc = &(sc->sc_ar_fpsr); 73169689Skan context->pfs_loc = &(sc->sc_ar_pfs); 74169689Skan context->lc_loc = &(sc->sc_ar_lc); 75169689Skan context->unat_loc = &(sc->sc_ar_unat); 76169689Skan context->br_loc[0] = &(sc->sc_br[0]); 77169689Skan context->br_loc[6] = &(sc->sc_br[6]); 78169689Skan context->br_loc[7] = &(sc->sc_br[7]); 79169689Skan context->pr = sc->sc_pr; 80169689Skan context->psp = sc->sc_gr[12]; 81169689Skan context->gp = sc->sc_gr[1]; 82169689Skan /* Signal frame doesn't have an associated reg. stack frame 83169689Skan other than what we adjust for below. */ 84169689Skan fs -> no_reg_stack_frame = 1; 85169689Skan 86169689Skan if (sc->sc_rbs_base) 87169689Skan { 88169689Skan /* Need to switch from alternate register backing store. */ 89169689Skan long ndirty, loadrs = sc->sc_loadrs >> 16; 90169689Skan unsigned long alt_bspstore = context->bsp - loadrs; 91169689Skan unsigned long bspstore; 92169689Skan unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp); 93169689Skan 94169689Skan ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, 95169689Skan (unsigned long *) context->bsp); 96169689Skan bspstore = (unsigned long) 97169689Skan ia64_rse_skip_regs (ar_bsp, -ndirty); 98169689Skan ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs, 99169689Skan sc->sc_ar_rnat); 100169689Skan } 101169689Skan 102169689Skan /* Don't touch the branch registers o.t. b0, b6 and b7. 103169689Skan The kernel doesn't pass the preserved branch registers 104169689Skan in the sigcontext but leaves them intact, so there's no 105169689Skan need to do anything with them here. */ 106169689Skan { 107169689Skan unsigned long sof = sc->sc_cfm & 0x7f; 108169689Skan context->bsp = (unsigned long) 109169689Skan ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof); 110169689Skan } 111169689Skan 112169689Skan fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL; 113169689Skan fs->curr.reg[UNW_REG_RP].val 114169689Skan = (unsigned long)&(sc->sc_ip) - context->psp; 115169689Skan fs->curr.reg[UNW_REG_RP].when = -1; 116169689Skan 117169689Skan return _URC_NO_REASON; 118169689Skan } 119169689Skan return _URC_END_OF_STACK; 120169689Skan} 121169689Skan 122169689Skan#define MD_HANDLE_UNWABI ia64_handle_unwabi 123169689Skan 124169689Skanstatic void 125169689Skania64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs) 126169689Skan{ 127169689Skan if (fs->unwabi == ((3 << 8) | 's') 128169689Skan || fs->unwabi == ((0 << 8) | 's')) 129169689Skan { 130169689Skan struct sigframe { 131169689Skan char scratch[16]; 132169689Skan unsigned long sig_number; 133169689Skan struct siginfo *info; 134169689Skan struct sigcontext *sc; 135169689Skan } *frame = (struct sigframe *)context->psp; 136169689Skan struct sigcontext *sc = frame->sc; 137169689Skan 138169689Skan /* Restore scratch registers in case the unwinder needs to 139169689Skan refer to a value stored in one of them. */ 140169689Skan { 141169689Skan int i; 142169689Skan 143169689Skan for (i = 2; i < 4; i++) 144169689Skan context->ireg[i - 2].loc = &sc->sc_gr[i]; 145169689Skan for (i = 8; i < 12; i++) 146169689Skan context->ireg[i - 2].loc = &sc->sc_gr[i]; 147169689Skan for (i = 14; i < 32; i++) 148169689Skan context->ireg[i - 2].loc = &sc->sc_gr[i]; 149169689Skan } 150169689Skan 151169689Skan context->pfs_loc = &(sc->sc_ar_pfs); 152169689Skan context->lc_loc = &(sc->sc_ar_lc); 153169689Skan context->unat_loc = &(sc->sc_ar_unat); 154169689Skan context->br_loc[0] = &(sc->sc_br[0]); 155169689Skan context->br_loc[6] = &(sc->sc_br[6]); 156169689Skan context->br_loc[7] = &(sc->sc_br[7]); 157169689Skan context->pr = sc->sc_pr; 158169689Skan context->gp = sc->sc_gr[1]; 159169689Skan /* Signal frame doesn't have an associated reg. stack frame 160169689Skan other than what we adjust for below. */ 161169689Skan fs -> no_reg_stack_frame = 1; 162169689Skan 163169689Skan if (sc->sc_rbs_base) 164169689Skan { 165169689Skan /* Need to switch from alternate register backing store. */ 166169689Skan long ndirty, loadrs = sc->sc_loadrs >> 16; 167169689Skan unsigned long alt_bspstore = context->bsp - loadrs; 168169689Skan unsigned long bspstore; 169169689Skan unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp); 170169689Skan 171169689Skan ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, 172169689Skan (unsigned long *) context->bsp); 173169689Skan bspstore = (unsigned long) ia64_rse_skip_regs (ar_bsp, -ndirty); 174169689Skan ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs, 175169689Skan sc->sc_ar_rnat); 176169689Skan } 177169689Skan 178169689Skan /* Don't touch the branch registers o.t. b0, b6 and b7. 179169689Skan The kernel doesn't pass the preserved branch registers 180169689Skan in the sigcontext but leaves them intact, so there's no 181169689Skan need to do anything with them here. */ 182169689Skan { 183169689Skan unsigned long sof = sc->sc_cfm & 0x7f; 184169689Skan context->bsp = (unsigned long) 185169689Skan ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof); 186169689Skan } 187169689Skan 188169689Skan /* pfs_loc already set above. Without this pfs_loc would point 189169689Skan incorrectly to sc_cfm instead of sc_ar_pfs. */ 190169689Skan fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE; 191169689Skan } 192169689Skan} 193169689Skan#endif /* glibc-2.3 or better */ 194