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