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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [ia64/] [vms-unwind.h] - Blame information for rev 298

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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