annotate libgcc/config/ia64/vms-unwind.h @ 120:f93fa5091070

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