OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [ia64/] [vms-unwind.h] - Blame information for rev 734

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* DWARF2 EH unwinding support for IA64 VMS.
2
   Copyright (C) 2005-2011 Free Software Foundation, Inc.
3
 
4
   This file is part of GCC.
5
 
6
   GCC is free software; you can redistribute it and/or modify it
7
   under the terms of the GNU General Public License as published
8
   by the Free Software Foundation; either version 3, or (at your
9
   option) any later version.
10
 
11
   GCC is distributed in the hope that it will be useful, but WITHOUT
12
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14
   License for more details.
15
 
16
   Under Section 7 of GPL version 3, you are granted additional
17
   permissions described in the GCC Runtime Library Exception, version
18
   3.1, as published by the Free Software Foundation.
19
 
20
   You should have received a copy of the GNU General Public License and
21
   a copy of the GCC Runtime Library Exception along with this program;
22
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
   <http://www.gnu.org/licenses/>.  */
24
 
25
#include <vms/libicb.h>
26
#include <vms/chfdef.h>
27
#include <vms/chfctxdef.h>
28
 
29
#define __int64 long long
30
#include <vms/intstkdef.h>
31
 
32
#include <stdio.h>
33
#include <string.h>
34
 
35
#define UNW_IVMS_MODE(HEADER) (((HEADER) >> 44) & 0x3L)
36
#define MD_UNW_COMPATIBLE_PERSONALITY_P(HEADER) (!UNW_IVMS_MODE (HEADER))
37
 
38
#define DYN$C_SSENTRY 66
39
/* ??? would rather get the proper header file.  */
40
 
41
#define MD_FALLBACK_FRAME_STATE_FOR ia64_vms_fallback_frame_state
42
 
43
extern INVO_CONTEXT_BLK * LIB$I64_CREATE_INVO_CONTEXT (void);
44
 
45
extern int LIB$I64_IS_EXC_DISPATCH_FRAME (void *);
46
extern int LIB$I64_IS_AST_DISPATCH_FRAME (void *);
47
 
48
extern int LIB$I64_INIT_INVO_CONTEXT (INVO_CONTEXT_BLK *, int, int);
49
extern int LIB$I64_GET_CURR_INVO_CONTEXT (INVO_CONTEXT_BLK *);
50
extern int LIB$I64_GET_PREV_INVO_CONTEXT (INVO_CONTEXT_BLK *);
51
 
52
typedef unsigned long ulong;
53
typedef unsigned int uint;
54
typedef unsigned long uw_reg;
55
typedef uw_reg * uw_loc;
56
 
57
typedef char fp_reg[16];
58
 
59
#define DENOTES_VMS_DISPATCHER_FRAME(icb) \
60
(LIB$I64_IS_EXC_DISPATCH_FRAME (&(icb)->libicb$ih_pc))
61
 
62
#define DENOTES_BOTTOM_OF_STACK(icb) ((icb)->libicb$v_bottom_of_stack)
63
 
64
#define FAIL_IF(COND) \
65
   do { if (COND) { context->rp = 0; return _URC_END_OF_STACK; } } while (0)
66
/* Clearing context->rp is required to prevent the ia64 gcc unwinder from
67
   attempting to keep on walking the call chain.  */
68
 
69
static int
70
ia64_vms_fallback_frame_state (struct _Unwind_Context *context,
71
                               _Unwind_FrameState *fs)
72
{
73
  int i, status;
74
 
75
  INVO_CONTEXT_BLK local_icb;
76
  INVO_CONTEXT_BLK *icb = &local_icb;
77
 
78
  CHFCTX * chfctx;
79
  CHF$MECH_ARRAY * chfmech;
80
  CHF64$SIGNAL_ARRAY *chfsig64;
81
  INTSTK * intstk;
82
 
83
  static int eh_debug = -1;
84
  int try_bs_copy = 0;
85
  /* Non zero to attempt copy of alternate backing store contents for
86
     dirty partition in interrupted context. ??? Alpha code, only activated
87
     on specific request via specific bit in EH_DEBUG.  */
88
 
89
  if (eh_debug == -1)
90
    {
91
      char * EH_DEBUG = getenv ("EH_DEBUG");
92
      const uint try_bs_copy_mask = (1 << 16);
93
 
94
      eh_debug = EH_DEBUG ? atoi (EH_DEBUG) : 0;
95
 
96
      /* Fetch and clear the try_bs_copy bit.  */
97
      try_bs_copy = (uint)eh_debug & try_bs_copy_mask;
98
      eh_debug &= ~try_bs_copy_mask;
99
    }
100
 
101
  /* We're called to attempt unwinding through a frame for which no unwind
102
     info is available, typical of an operating system exception dispatcher
103
     frame.  The code below knows how to handle this case, and only this one,
104
     returning a failure code if it finds it is not in this situation.
105
 
106
     Note that we're called from deep down in the exception propagation call
107
     chain, possibly below an exception dispatcher but for a frame above it
108
     like some os entry point.  */
109
 
110
  if (eh_debug)
111
    printf ("FALLBACK - ctxt->rp=0x%lx, sp=0x%lx, psp=0x%lx, bsp=0x%lx\n",
112
            context->rp, context->sp, context->psp, context->bsp);
113
 
114
  /* Step 0 :
115
     -------------------------------------------------------------------------
116
     VMS-unwind up until we reach a VMS dispatcher frame corresponding to the
117
     context we are trying to unwind through. Fail if get past this context or
118
     if we reach the bottom of stack along the way.
119
     -------------------------------------------------------------------------
120
  */
121
 
122
  status = LIB$I64_INIT_INVO_CONTEXT (icb, LIBICB$K_INVO_CONTEXT_VERSION, 0);
123
  FAIL_IF (status == 0);
124
 
125
  status = LIB$I64_GET_CURR_INVO_CONTEXT (icb);
126
 
127
  /* Beware: we might be unwinding through nested condition handlers, so the
128
     dispatcher frame we seek might not be the first one on the way up.  Loop
129
     thus.  */
130
  do {
131
 
132
    /* Seek the next dispatcher frame up the "current" point.  Stop if we
133
       either get past the target context or hit the bottom-of-stack along
134
       the way.  */
135
    status = LIB$I64_GET_PREV_INVO_CONTEXT (icb);
136
    FAIL_IF (status == 0);
137
    FAIL_IF ((uw_reg)icb->libicb$ih_sp > (uw_reg)context->psp
138
             || DENOTES_BOTTOM_OF_STACK (icb));
139
 
140
    if (eh_debug)
141
      printf ("frame%s sp @ 0x%llx, pc @ 0x%llx bsp=0x%llx\n",
142
              DENOTES_VMS_DISPATCHER_FRAME (icb) ? " (dispatcher)" : "",
143
              icb->libicb$ih_sp, icb->libicb$ih_pc, icb->libicb$ih_bsp);
144
 
145
    /* Continue until the target frame is found.  */
146
  } while ((uw_reg)icb->libicb$ih_bsp != (uw_reg)context->bsp);
147
 
148
  /* If this is not a dispatcher frame, this is certainly a frame for a leaf
149
     subprogram.  Use default unwind information.  */
150
  if (! DENOTES_VMS_DISPATCHER_FRAME (icb))
151
    return _URC_END_OF_STACK;
152
 
153
  /* At this point, we know we are really trying to unwind past an exception
154
     dispatcher frame, and have it described in ICB.  Proceed.  */
155
 
156
  /* Step 1 :
157
     ------------------------------------------------------------------------
158
     We have the VMS dispatcher frame ICB handy and know we are trying to
159
     unwind past it.  Fetch pointers to useful datastructures from there, then
160
     unwind one step further up to the interrupted user context from which
161
     some required values will be easily accessible.
162
     ------------------------------------------------------------------------
163
  */
164
 
165
  chfctx = icb->libicb$ph_chfctx_addr;
166
  FAIL_IF (chfctx == 0);
167
 
168
  chfmech = (CHF$MECH_ARRAY *)chfctx->chfctx$q_mcharglst;
169
  FAIL_IF (chfmech == 0);
170
 
171
  chfsig64 = (CHF64$SIGNAL_ARRAY *)chfmech->chf$ph_mch_sig64_addr;
172
  FAIL_IF (chfsig64 == 0);
173
 
174
  intstk = (INTSTK *)chfmech->chf$q_mch_esf_addr;
175
  FAIL_IF (intstk == 0 || intstk->intstk$b_subtype == DYN$C_SSENTRY);
176
 
177
  status = LIB$I64_GET_PREV_INVO_CONTEXT (icb);
178
  FAIL_IF (status == 0);
179
 
180
  if (eh_debug)
181
    printf ("User frame, "
182
            "chfmech @ 0x%lx, chfsig64 @ 0x%lx, intstk @ 0x%lx\n",
183
            (ulong)chfmech, (ulong)chfsig64, (ulong)intstk);
184
 
185
  /* Step 2 :
186
     ------------------------------------------------------------------------
187
     Point the GCC context locations/values required for further unwinding at
188
     their corresponding locations/values in the datastructures at hand.
189
     ------------------------------------------------------------------------
190
  */
191
 
192
  /* Static General Register locations, including scratch registers in case
193
     the unwinder needs to refer to a value stored in one of them.  */
194
  {
195
    uw_reg * ctxregs = (uw_reg *)&intstk->intstk$q_regbase;
196
 
197
    for (i = 2; i <= 3; i++)
198
      context->ireg[i - 2].loc = (uw_loc)&ctxregs[i];
199
    for (i = 8; i <= 11; i++)
200
      context->ireg[i - 2].loc = (uw_loc)&ctxregs[i];
201
    for (i = 14; i <= 31; i++)
202
      context->ireg[i - 2].loc = (uw_loc)&ctxregs[i];
203
  }
204
 
205
  /* Static Floating Point Register locations, as available from the
206
     mechargs array, which happens to include all the to be preserved
207
     ones + others.  */
208
  {
209
    fp_reg * ctxregs;
210
 
211
    ctxregs = (fp_reg *)&chfmech->chf$fh_mch_savf2;
212
    for (i = 2; i <= 5 ; i++)
213
      context->fr_loc[i - 2] = (uw_loc)&ctxregs[i - 2];
214
 
215
    ctxregs = (fp_reg *)&chfmech->chf$fh_mch_savf12;
216
    for (i = 12; i <= 31 ; i++)
217
      context->fr_loc[i - 2] = (uw_loc)&ctxregs[i - 12];
218
  }
219
 
220
  /* Relevant application register locations.  */
221
 
222
  context->fpsr_loc = (uw_loc)&intstk->intstk$q_fpsr;
223
  context->lc_loc   = (uw_loc)&intstk->intstk$q_lc;
224
  context->unat_loc = (uw_loc)&intstk->intstk$q_unat;
225
 
226
  /* Branch register locations.  */
227
 
228
  {
229
    uw_reg * ctxregs = (uw_reg *)&intstk->intstk$q_b0;
230
 
231
    for (i = 0; i < 8; i++)
232
      context->br_loc[i] = (uw_loc)&ctxregs[i];
233
  }
234
 
235
  /* Necessary register values.  */
236
 
237
  /* ??? Still unclear if we need to account for possible flushes to an
238
     alternate backing store (maybe the unwinding performed above did the
239
     trick already) and how this would be handled.  Blind alpha tentative
240
     below for experimentation purposes in malfunctioning cases.  */
241
  {
242
    ulong q_bsp      = (ulong) intstk->intstk$q_bsp;
243
    ulong q_bspstore = (ulong) intstk->intstk$q_bspstore;
244
    ulong q_bspbase  = (ulong) intstk->intstk$q_bspbase;
245
    ulong ih_bspbase = (ulong) icb->libicb$ih_bspbase;
246
 
247
    if (eh_debug)
248
      printf ("q_bspstore = 0x%lx, q_bsp = 0x%lx, q_bspbase = 0x%lx\n"
249
              "ih_bspbase = 0x%lx\n",
250
              q_bspstore, q_bsp, q_bspbase, ih_bspbase);
251
 
252
    /* We witness many situations where q_bspbase is set while ih_bspbase is
253
       null, and every attempt made with q_bspbase badly failed while doing
254
       nothing resulted in proper behavior.  */
255
    if (q_bspstore < q_bsp && ih_bspbase && try_bs_copy)
256
      {
257
        ulong dirty_size = q_bsp - q_bspstore;
258
        ulong q_rnat = (ulong) intstk->intstk$q_rnat;
259
 
260
        if (eh_debug)
261
          printf ("Attempting an alternate backing store copy ...\n");
262
 
263
        ia64_copy_rbs
264
          (context, q_bspstore, ih_bspbase, dirty_size, q_rnat);
265
        /* Not clear if these are the proper arguments here.  This is what
266
           looked the closest to what is performed in the Linux case.  */
267
      }
268
 
269
  }
270
 
271
  context->bsp = (uw_reg)intstk->intstk$q_bsp;
272
  fs->no_reg_stack_frame = 1;
273
 
274
  context->pr  = (uw_reg)intstk->intstk$q_preds;
275
  context->gp  = (uw_reg)intstk->intstk$q_gp;
276
 
277
  /* We're directly setting up the "context" for a VMS exception handler.
278
     The "previous SP" for it is the SP upon the handler's entry, that is
279
     the SP at the condition/interruption/exception point.  */
280
  context->psp = (uw_reg)icb->libicb$ih_sp;
281
 
282
  /* Previous Frame State location.  What eventually ends up in pfs_loc is
283
     installed with ar.pfs = pfs_loc; br.ret; so setup to target intstk->q_ifs
284
     to have the interrupted context restored and not that of its caller if
285
     we happen to have a handler in the interrupted context itself.  */
286
  fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_PSPREL;
287
  fs->curr.reg[UNW_REG_PFS].val
288
    = (uw_reg)&intstk->intstk$q_ifs - (uw_reg)context->psp;
289
  fs->curr.reg[UNW_REG_PFS].when = -1;
290
 
291
  /* If we need to unwind further up, past the interrupted context, we need to
292
     hand out the interrupted context's pfs, still.  */
293
  context->signal_pfs_loc = (uw_loc) &intstk->intstk$q_pfs;
294
 
295
  /* Finally, rules for RP .  */
296
  {
297
    uw_reg * post_sigarray
298
      = (uw_reg *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
299
 
300
    uw_reg * ih_pc_loc = post_sigarray - 2;
301
 
302
    fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_PSPREL;
303
    fs->curr.reg[UNW_REG_RP].val
304
      = (uw_reg)ih_pc_loc - (uw_reg)context->psp;
305
    fs->curr.reg[UNW_REG_RP].when = -1;
306
  }
307
 
308
  return _URC_NO_REASON;
309
}
310
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.