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