1/* Fallback frame unwinding for Alpha/VMS. 2 Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2009 3 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published 9 by the Free Software Foundation; either version 3, or (at your 10 option) any later version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 Under Section 7 of GPL version 3, you are granted additional 18 permissions described in the GCC Runtime Library Exception, version 19 3.1, as published by the Free Software Foundation. 20 21 You should have received a copy of the GNU General Public License and 22 a copy of the GCC Runtime Library Exception along with this program; 23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 <http://www.gnu.org/licenses/>. */ 25 26#include <stdlib.h> 27#include <stdio.h> 28#include <vms/pdscdef.h> 29#include <vms/libicb.h> 30#include <vms/chfctxdef.h> 31#include <vms/chfdef.h> 32 33#define MD_FALLBACK_FRAME_STATE_FOR alpha_vms_fallback_frame_state 34 35typedef void * ADDR; 36typedef unsigned long long REG; 37typedef PDSCDEF * PV; 38 39#define REG_AT(addr) (*(REG *)(addr)) 40#define ADDR_AT(addr) (*(ADDR *)(addr)) 41 42/* Compute pointer to procedure descriptor (Procedure Value) from Frame 43 Pointer FP, according to the rules in [ABI-3.5.1 Current Procedure]. */ 44#define PV_FOR(FP) \ 45 (((FP) != 0) \ 46 ? (((REG_AT (FP) & 0x7) == 0) ? *(PDSCDEF **)(FP) : (PDSCDEF *)(FP)) : 0) 47 48extern int SYS$GL_CALL_HANDL; 49/* This is actually defined as a "long", but in system code where longs 50 are always 4bytes while GCC longs might be 8bytes. */ 51 52#define UPDATE_FS_FOR_CFA_GR(FS, GRN, LOC, CFA) \ 53do { \ 54(FS)->regs.reg[GRN].how = REG_SAVED_OFFSET; \ 55(FS)->regs.reg[GRN].loc.offset = (_Unwind_Sword) ((REG) (LOC) - (REG) (CFA)); \ 56} while (0); 57 58#define GIVEUP_ON_FAILURE(STATUS) \ 59 { if ((((STATUS) & 1) != 1)) return _URC_END_OF_STACK; } 60#define DENOTES_EXC_DISPATCHER(PV) ((PV) == (ADDR) (REG) SYS$GL_CALL_HANDL) 61 62#define RA_COLUMN (DWARF_ALT_FRAME_RETURN_COLUMN) 63 64static int 65alpha_vms_fallback_frame_state (struct _Unwind_Context *context, 66 _Unwind_FrameState *fs) 67{ 68 static int eh_debug = -1; 69 70 /* Our goal is to update FS to reflect the state one step up CONTEXT, that 71 is: the CFA, return address and *saved* registers locations associated 72 with the function designated by CONTEXT->ra. We are called when the 73 libgcc unwinder has not found any dwarf FDE for this address, which 74 typically happens when trying to propagate a language exception through a 75 signal global vector or frame based handler. 76 77 The CONTEXT->reg[] entries reflect the state/location of register saves 78 so designate values live at the CONTEXT->ra point. Of precious value to 79 us here is the frame pointer (r29), which gets us a procedure value. */ 80 81 PV pv = (context->reg[29] != 0) ? PV_FOR (ADDR_AT (context->reg[29])) : 0; 82 83 int pkind = pv ? pv->pdsc$w_flags & 0xf : 0; 84 /* VMS procedure kind, as indicated by the procedure descriptor. We only 85 know how to deal with FP_STACK or FP_REGISTER here. */ 86 87 ADDR new_cfa = 0; 88 /* CFA we will establish for the caller, computed in different ways, 89 e.g. depending whether we cross an exception dispatcher frame. */ 90 91 CHFCTX *chfctx = 0; 92 /* Pointer to the VMS CHF context associated with an exception dispatcher 93 frame, if we happen to come across one. */ 94 95 int i,j; 96 97 if (eh_debug == -1) 98 { 99 char * eh_debug_env = getenv ("EH_DEBUG"); 100 eh_debug = eh_debug_env ? atoi (eh_debug_env) : 0; 101 } 102 103 if (eh_debug) 104 printf ("MD_FALLBACK running ...\n"); 105 106 /* We only know how to deal with stack or reg frame procedures, so give 107 up if we're handed anything else. */ 108 if (pkind != PDSC$K_KIND_FP_STACK && pkind != PDSC$K_KIND_FP_REGISTER) 109 return _URC_END_OF_STACK; 110 111 if (eh_debug) 112 printf ("FALLBACK: CTX FP = 0x%p, PV = 0x%p, EN = 0x%llx, RA = 0x%p\n", 113 ADDR_AT (context->reg[29]), pv, pv->pdsc$q_entry, context->ra); 114 115 fs->retaddr_column = RA_COLUMN; 116 117 /* If PV designates a VMS exception vector or condition handler, we need to 118 do as if the caller was the signaling point and estabish the state of the 119 intermediate VMS code (CFA, RA and saved register locations) as if it was 120 a single regular function. This requires special processing. 121 122 The datastructures available from an condition dispatcher frame (signal 123 context) do not contain the values of most callee-saved registers, so 124 whathever PV designates, we need to account for the registers it saves. 125 126 Besides, we need to express all the locations with respect to a 127 consistent CFA value, so we compute this first. */ 128 129 if (DENOTES_EXC_DISPATCHER (pv)) 130 { 131 /* The CFA to establish is the signaling point's stack pointer. We 132 compute it using the system invocation context unwinding services and 133 save the CHF context data pointer along the way for later uses. */ 134 135 INVO_CONTEXT_BLK icb; 136 int status, invo_handle; 137 138 if (eh_debug) 139 printf ("FALLBACK: SYS$HANDLER\n"); 140 141 icb.libicb$q_ireg [29] = REG_AT (context->reg[29]); 142 icb.libicb$q_ireg [30] = 0; 143 invo_handle = LIB$GET_INVO_HANDLE (&icb); 144 145 status = LIB$GET_INVO_CONTEXT (invo_handle, &icb); 146 GIVEUP_ON_FAILURE (status); 147 148 chfctx = (CHFCTX *) icb.libicb$ph_chfctx_addr; 149 150 status = LIB$GET_PREV_INVO_CONTEXT (&icb); 151 GIVEUP_ON_FAILURE (status); 152 153 new_cfa = (ADDR) icb.libicb$q_ireg[30]; 154 } 155 else 156 { 157 /* The CFA to establish is the SP value on entry of the procedure 158 designated by PV, which we compute as the corresponding frame base 159 register value + frame size. Note that the frame base may differ 160 from CONTEXT->cfa, typically if the caller has performed dynamic 161 stack allocations. */ 162 163 int base_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; 164 ADDR base_addr = ADDR_AT (context->reg[base_reg]); 165 166 new_cfa = base_addr + pv->pdsc$l_size; 167 } 168 169 /* State to compute the caller's CFA by adding an offset to the current 170 one in CONTEXT. */ 171 fs->regs.cfa_how = CFA_REG_OFFSET; 172 fs->regs.cfa_reg = __builtin_dwarf_sp_column (); 173 fs->regs.cfa_offset = new_cfa - context->cfa; 174 175 /* Regular unwind first, accounting for the register saves performed by 176 the procedure designated by PV. */ 177 178 switch (pkind) 179 { 180 case PDSC$K_KIND_FP_STACK: 181 { 182 /* The saved registers are all located in the Register Save Area, 183 except for the procedure value register (R27) found at the frame 184 base address. */ 185 186 int base_reg = pv->pdsc$w_flags & PDSC$M_BASE_REG_IS_FP ? 29 : 30; 187 ADDR base_addr = ADDR_AT (context->reg[base_reg]); 188 ADDR rsa_addr = base_addr + pv->pdsc$w_rsa_offset; 189 190 if (eh_debug) 191 printf ("FALLBACK: STACK frame procedure\n"); 192 193 UPDATE_FS_FOR_CFA_GR (fs, 27, base_addr, new_cfa); 194 195 /* The first RSA entry is for the return address register, R26. */ 196 197 UPDATE_FS_FOR_CFA_GR (fs, 26, rsa_addr, new_cfa); 198 UPDATE_FS_FOR_CFA_GR (fs, RA_COLUMN, rsa_addr, new_cfa); 199 200 /* The following entries are for registers marked as saved according 201 to ireg_mask. */ 202 for (i = 0, j = 0; i < 32; i++) 203 if ((1 << i) & pv->pdsc$l_ireg_mask) 204 UPDATE_FS_FOR_CFA_GR (fs, i, rsa_addr + 8 * ++j, new_cfa); 205 206 /* ??? floating point registers ? */ 207 208 break; 209 } 210 211 case PDSC$K_KIND_FP_REGISTER: 212 { 213 if (eh_debug) 214 printf ("FALLBACK: REGISTER frame procedure\n"); 215 216 fs->regs.reg[RA_COLUMN].how = REG_SAVED_REG; 217 fs->regs.reg[RA_COLUMN].loc.reg = pv->pdsc$b_save_ra; 218 219 fs->regs.reg[29].how = REG_SAVED_REG; 220 fs->regs.reg[29].loc.reg = pv->pdsc$b_save_fp; 221 222 break; 223 } 224 225 default: 226 /* Should never reach here. */ 227 return _URC_END_OF_STACK; 228 } 229 230 /* If PV designates an exception dispatcher, we have to adjust the return 231 address column to get at the signal occurrence point, and account for 232 for what the CHF context contains. */ 233 234 if (DENOTES_EXC_DISPATCHER (pv)) 235 { 236 /* The PC of the instruction causing the condition is available from the 237 signal argument vector. Extra saved register values are available 238 from the mechargs array. */ 239 240 CHF$SIGNAL_ARRAY *sigargs 241 = (CHF$SIGNAL_ARRAY *) chfctx->chfctx$q_sigarglst; 242 243 CHF$MECH_ARRAY *mechargs 244 = (CHF$MECH_ARRAY *) chfctx->chfctx$q_mcharglst; 245 246 ADDR condpc_addr 247 = &((int *)(&sigargs->chf$l_sig_name)) [sigargs->chf$is_sig_args-2]; 248 249 ADDR rei_frame_addr = (void *) mechargs->chf$q_mch_esf_addr; 250 251 /* Adjust the return address location. */ 252 253 UPDATE_FS_FOR_CFA_GR (fs, RA_COLUMN, condpc_addr, new_cfa); 254 255 /* The frame pointer at the condition point is available from the 256 chf context directly. */ 257 258 UPDATE_FS_FOR_CFA_GR (fs, 29, &chfctx->chfctx$q_expt_fp, new_cfa); 259 260 /* Registers available from the mechargs array. */ 261 262 UPDATE_FS_FOR_CFA_GR (fs, 0, &mechargs->chf$q_mch_savr0, new_cfa); 263 UPDATE_FS_FOR_CFA_GR (fs, 1, &mechargs->chf$q_mch_savr1, new_cfa); 264 265 UPDATE_FS_FOR_CFA_GR (fs, 16, &mechargs->chf$q_mch_savr16, new_cfa); 266 UPDATE_FS_FOR_CFA_GR (fs, 17, &mechargs->chf$q_mch_savr17, new_cfa); 267 UPDATE_FS_FOR_CFA_GR (fs, 18, &mechargs->chf$q_mch_savr18, new_cfa); 268 UPDATE_FS_FOR_CFA_GR (fs, 19, &mechargs->chf$q_mch_savr19, new_cfa); 269 UPDATE_FS_FOR_CFA_GR (fs, 20, &mechargs->chf$q_mch_savr20, new_cfa); 270 UPDATE_FS_FOR_CFA_GR (fs, 21, &mechargs->chf$q_mch_savr21, new_cfa); 271 UPDATE_FS_FOR_CFA_GR (fs, 22, &mechargs->chf$q_mch_savr22, new_cfa); 272 UPDATE_FS_FOR_CFA_GR (fs, 23, &mechargs->chf$q_mch_savr23, new_cfa); 273 UPDATE_FS_FOR_CFA_GR (fs, 24, &mechargs->chf$q_mch_savr24, new_cfa); 274 UPDATE_FS_FOR_CFA_GR (fs, 25, &mechargs->chf$q_mch_savr25, new_cfa); 275 UPDATE_FS_FOR_CFA_GR (fs, 26, &mechargs->chf$q_mch_savr26, new_cfa); 276 UPDATE_FS_FOR_CFA_GR (fs, 27, &mechargs->chf$q_mch_savr27, new_cfa); 277 UPDATE_FS_FOR_CFA_GR (fs, 28, &mechargs->chf$q_mch_savr28, new_cfa); 278 279 /* Registers R2 to R7 are available from the rei frame pointer. */ 280 281 for (i = 2; i <= 7; i ++) 282 UPDATE_FS_FOR_CFA_GR (fs, i, rei_frame_addr+(i - 2)*8, new_cfa); 283 284 /* ??? floating point registers ? */ 285 } 286 287 return _URC_NO_REASON; 288} 289 290 291 292