linux-unwind.h revision 256281
1227569Sphilip/* DWARF2 EH unwinding support for IA64 Linux. 2284555Sarybchik Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3284555Sarybchik 4227569Sphilip This file is part of GCC. 5227569Sphilip 6284555Sarybchik GCC is free software; you can redistribute it and/or modify it 7227569Sphilip under the terms of the GNU General Public License as published 8284555Sarybchik by the Free Software Foundation; either version 2, or (at your 9284555Sarybchik option) any later version. 10284555Sarybchik 11284555Sarybchik In addition to the permissions in the GNU General Public License, 12284555Sarybchik the Free Software Foundation gives you unlimited permission to link 13228078Sphilip the compiled version of this file with other programs, and to 14284555Sarybchik distribute those programs without any restriction coming from the 15284555Sarybchik use of this file. (The General Public License restrictions do 16284555Sarybchik apply in other respects; for example, they cover modification of 17284555Sarybchik the file, and distribution when not linked into another program.) 18284555Sarybchik 19284555Sarybchik GCC is distributed in the hope that it will be useful, but WITHOUT 20284555Sarybchik ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 21284555Sarybchik or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 22284555Sarybchik License for more details. 23284555Sarybchik 24284555Sarybchik You should have received a copy of the GNU General Public License 25284555Sarybchik along with GCC; see the file COPYING. If not, write to the 26284555Sarybchik Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 27284555Sarybchik MA 02110-1301, USA. */ 28284555Sarybchik 29284555Sarybchik/* Do code reading to identify a signal frame, and set the frame 30228078Sphilip state data appropriately. See unwind-dw2.c for the structs. */ 31227569Sphilip 32227569Sphilip/* This works only for glibc-2.3 and later, because sigcontext is different 33227569Sphilip in glibc-2.2.4. */ 34227569Sphilip 35227569Sphilip#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) 36227569Sphilip#include <signal.h> 37227569Sphilip#include <sys/ucontext.h> 38227569Sphilip 39227569Sphilip#define IA64_GATE_AREA_START 0xa000000000000100LL 40227569Sphilip#define IA64_GATE_AREA_END 0xa000000000030000LL 41227569Sphilip 42227569Sphilip#define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state 43227569Sphilip 44227569Sphilipstatic _Unwind_Reason_Code 45227569Sphilipia64_fallback_frame_state (struct _Unwind_Context *context, 46227569Sphilip _Unwind_FrameState *fs) 47227569Sphilip{ 48227569Sphilip if (context->rp >= IA64_GATE_AREA_START 49227569Sphilip && context->rp < IA64_GATE_AREA_END) 50227569Sphilip { 51227569Sphilip struct sigframe { 52227569Sphilip char scratch[16]; 53227569Sphilip unsigned long sig_number; 54227569Sphilip struct siginfo *info; 55227569Sphilip struct sigcontext *sc; 56227569Sphilip } *frame_ = (struct sigframe *)context->psp; 57227569Sphilip struct sigcontext *sc = frame_->sc; 58293927Sarybchik 59227569Sphilip /* Restore scratch registers in case the unwinder needs to 60227569Sphilip refer to a value stored in one of them. */ 61227569Sphilip { 62227569Sphilip int i; 63227569Sphilip 64293927Sarybchik for (i = 2; i < 4; i++) 65227569Sphilip context->ireg[i - 2].loc = &sc->sc_gr[i]; 66227569Sphilip for (i = 8; i < 12; i++) 67227569Sphilip context->ireg[i - 2].loc = &sc->sc_gr[i]; 68227569Sphilip for (i = 14; i < 32; i++) 69227569Sphilip context->ireg[i - 2].loc = &sc->sc_gr[i]; 70293927Sarybchik } 71227569Sphilip 72227569Sphilip context->fpsr_loc = &(sc->sc_ar_fpsr); 73227569Sphilip context->pfs_loc = &(sc->sc_ar_pfs); 74293927Sarybchik context->lc_loc = &(sc->sc_ar_lc); 75227569Sphilip context->unat_loc = &(sc->sc_ar_unat); 76227569Sphilip context->br_loc[0] = &(sc->sc_br[0]); 77227569Sphilip context->br_loc[6] = &(sc->sc_br[6]); 78227569Sphilip context->br_loc[7] = &(sc->sc_br[7]); 79227569Sphilip context->pr = sc->sc_pr; 80293927Sarybchik context->psp = sc->sc_gr[12]; 81227569Sphilip context->gp = sc->sc_gr[1]; 82227569Sphilip /* Signal frame doesn't have an associated reg. stack frame 83227569Sphilip other than what we adjust for below. */ 84227569Sphilip fs -> no_reg_stack_frame = 1; 85227569Sphilip 86227569Sphilip if (sc->sc_rbs_base) 87227569Sphilip { 88227569Sphilip /* Need to switch from alternate register backing store. */ 89227569Sphilip long ndirty, loadrs = sc->sc_loadrs >> 16; 90227569Sphilip unsigned long alt_bspstore = context->bsp - loadrs; 91227569Sphilip unsigned long bspstore; 92227569Sphilip unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp); 93227569Sphilip 94227569Sphilip ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, 95227569Sphilip (unsigned long *) context->bsp); 96227569Sphilip bspstore = (unsigned long) 97227569Sphilip ia64_rse_skip_regs (ar_bsp, -ndirty); 98227569Sphilip ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs, 99227569Sphilip sc->sc_ar_rnat); 100227569Sphilip } 101227569Sphilip 102293927Sarybchik /* Don't touch the branch registers o.t. b0, b6 and b7. 103227569Sphilip The kernel doesn't pass the preserved branch registers 104227569Sphilip in the sigcontext but leaves them intact, so there's no 105227569Sphilip need to do anything with them here. */ 106227569Sphilip { 107227569Sphilip unsigned long sof = sc->sc_cfm & 0x7f; 108227569Sphilip context->bsp = (unsigned long) 109284555Sarybchik ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof); 110227569Sphilip } 111293927Sarybchik 112284555Sarybchik fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL; 113284555Sarybchik fs->curr.reg[UNW_REG_RP].val 114284555Sarybchik = (unsigned long)&(sc->sc_ip) - context->psp; 115284555Sarybchik fs->curr.reg[UNW_REG_RP].when = -1; 116284555Sarybchik 117294378Sarybchik return _URC_NO_REASON; 118284555Sarybchik } 119294378Sarybchik return _URC_END_OF_STACK; 120294378Sarybchik} 121294378Sarybchik 122294378Sarybchik#define MD_HANDLE_UNWABI ia64_handle_unwabi 123284555Sarybchik 124293972Sarybchikstatic void 125293972Sarybchikia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs) 126293972Sarybchik{ 127293972Sarybchik if (fs->unwabi == ((3 << 8) | 's') 128293960Sarybchik || fs->unwabi == ((0 << 8) | 's')) 129293960Sarybchik { 130294017Sarybchik struct sigframe { 131294017Sarybchik char scratch[16]; 132294017Sarybchik unsigned long sig_number; 133294017Sarybchik struct siginfo *info; 134293960Sarybchik struct sigcontext *sc; 135293927Sarybchik } *frame = (struct sigframe *)context->psp; 136284555Sarybchik struct sigcontext *sc = frame->sc; 137284555Sarybchik 138284555Sarybchik /* Restore scratch registers in case the unwinder needs to 139284555Sarybchik refer to a value stored in one of them. */ 140284555Sarybchik { 141284555Sarybchik int i; 142284555Sarybchik 143293927Sarybchik for (i = 2; i < 4; i++) 144293969Sarybchik context->ireg[i - 2].loc = &sc->sc_gr[i]; 145284555Sarybchik for (i = 8; i < 12; i++) 146293969Sarybchik context->ireg[i - 2].loc = &sc->sc_gr[i]; 147284555Sarybchik for (i = 14; i < 32; i++) 148284555Sarybchik context->ireg[i - 2].loc = &sc->sc_gr[i]; 149284555Sarybchik } 150284555Sarybchik 151227569Sphilip context->pfs_loc = &(sc->sc_ar_pfs); 152227569Sphilip context->lc_loc = &(sc->sc_ar_lc); 153293927Sarybchik context->unat_loc = &(sc->sc_ar_unat); 154227569Sphilip context->br_loc[0] = &(sc->sc_br[0]); 155227569Sphilip context->br_loc[6] = &(sc->sc_br[6]); 156294002Sarybchik context->br_loc[7] = &(sc->sc_br[7]); 157227569Sphilip context->pr = sc->sc_pr; 158227569Sphilip context->gp = sc->sc_gr[1]; 159227569Sphilip /* Signal frame doesn't have an associated reg. stack frame 160227569Sphilip other than what we adjust for below. */ 161294002Sarybchik fs -> no_reg_stack_frame = 1; 162227569Sphilip 163293927Sarybchik if (sc->sc_rbs_base) 164227569Sphilip { 165227569Sphilip /* Need to switch from alternate register backing store. */ 166294002Sarybchik long ndirty, loadrs = sc->sc_loadrs >> 16; 167227569Sphilip unsigned long alt_bspstore = context->bsp - loadrs; 168227569Sphilip unsigned long bspstore; 169227569Sphilip unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp); 170227569Sphilip 171227569Sphilip ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, 172227569Sphilip (unsigned long *) context->bsp); 173227569Sphilip bspstore = (unsigned long) ia64_rse_skip_regs (ar_bsp, -ndirty); 174227569Sphilip ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs, 175227569Sphilip sc->sc_ar_rnat); 176227569Sphilip } 177293927Sarybchik 178227569Sphilip /* Don't touch the branch registers o.t. b0, b6 and b7. 179227569Sphilip The kernel doesn't pass the preserved branch registers 180227569Sphilip in the sigcontext but leaves them intact, so there's no 181227569Sphilip need to do anything with them here. */ 182227569Sphilip { 183293927Sarybchik unsigned long sof = sc->sc_cfm & 0x7f; 184284555Sarybchik context->bsp = (unsigned long) 185284555Sarybchik ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof); 186294002Sarybchik } 187284555Sarybchik 188284555Sarybchik /* pfs_loc already set above. Without this pfs_loc would point 189293927Sarybchik incorrectly to sc_cfm instead of sc_ar_pfs. */ 190294379Sarybchik fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE; 191227569Sphilip } 192227569Sphilip} 193294379Sarybchik#endif /* glibc-2.3 or better */ 194227569Sphilip