fde-vms.c revision 1.1 1 1.1 mrg /* Copyright (C) 2004-2013 Free Software Foundation, Inc.
2 1.1 mrg Contributed by Douglas B Rupp <rupp (at) gnat.com>
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
7 1.1 mrg it under the terms of the GNU General Public License as published by
8 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
9 1.1 mrg any later version.
10 1.1 mrg
11 1.1 mrg GCC is distributed in the hope that it will be useful,
12 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 mrg GNU General Public 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 /* Locate the FDE entry for a given address, using VMS Starlet routines
26 1.1 mrg to avoid register/deregister calls at DSO load/unload. */
27 1.1 mrg
28 1.1 mrg #include "tconfig.h"
29 1.1 mrg #include "tsystem.h"
30 1.1 mrg #include "coretypes.h"
31 1.1 mrg #include "tm.h"
32 1.1 mrg #include "libgcc_tm.h"
33 1.1 mrg #include <stddef.h>
34 1.1 mrg #include <stdlib.h>
35 1.1 mrg #include <stdio.h>
36 1.1 mrg #include "unwind-ia64.h"
37 1.1 mrg
38 1.1 mrg #include <ossddef.h>
39 1.1 mrg #ifndef SS$_NORMAL
40 1.1 mrg #define SS$_NORMAL 1
41 1.1 mrg #endif
42 1.1 mrg
43 1.1 mrg #define UNW_IVMS_MODE(HEADER) (((HEADER) >> 44) & 0x3L)
44 1.1 mrg
45 1.1 mrg typedef struct
46 1.1 mrg {
47 1.1 mrg unw_word start_offset;
48 1.1 mrg unw_word end_offset;
49 1.1 mrg unw_word info_offset;
50 1.1 mrg unw_word gp_value;
51 1.1 mrg } vms_unw_table_entry;
52 1.1 mrg
53 1.1 mrg typedef unsigned long long uqword;
54 1.1 mrg
55 1.1 mrg /* ENTRY is the unwind table entry found for a PC part of call chain we're
56 1.1 mrg unwinding through. Return whether we should force the generic unwinder
57 1.1 mrg to resort to "fallback" processing. */
58 1.1 mrg
59 1.1 mrg static int
60 1.1 mrg force_fallback_processing_for (void * pc, vms_unw_table_entry * entry)
61 1.1 mrg {
62 1.1 mrg static int eh_debug = -1;
63 1.1 mrg
64 1.1 mrg uqword * unw_info_block = (uqword *)entry->info_offset;
65 1.1 mrg uqword header = *unw_info_block;
66 1.1 mrg
67 1.1 mrg /* We need to force fallback processing in two cases:
68 1.1 mrg
69 1.1 mrg 1/ The exception dispatch frame, since only our fallback
70 1.1 mrg processing knows how to properly unwind through it, and
71 1.1 mrg
72 1.1 mrg 2/ A bottom of stack frame, since only our fallback processing
73 1.1 mrg will ensure we don't try to unwind further past it, which
74 1.1 mrg would get us into unknown territory and likely cause a severe
75 1.1 mrg crash along the way.
76 1.1 mrg
77 1.1 mrg The two cases are indicated by non-default values for specific
78 1.1 mrg bits in the OS Specific Data (OSSD) General Information block
79 1.1 mrg associated with such frames. */
80 1.1 mrg
81 1.1 mrg ossddef * ossd;
82 1.1 mrg
83 1.1 mrg if (eh_debug == -1)
84 1.1 mrg {
85 1.1 mrg char * EH_DEBUG = getenv ("EH_DEBUG");
86 1.1 mrg eh_debug = EH_DEBUG ? atoi (EH_DEBUG) : 0;
87 1.1 mrg }
88 1.1 mrg
89 1.1 mrg if (eh_debug)
90 1.1 mrg {
91 1.1 mrg printf ("pc @ 0x%p, block @ 0x%p, header = 0x%016llx\n",
92 1.1 mrg pc, unw_info_block, header);
93 1.1 mrg printf ("mode = %d, length = %ld, handler = %d\n",
94 1.1 mrg (int)UNW_IVMS_MODE (header), UNW_LENGTH (header),
95 1.1 mrg UNW_FLAG_EHANDLER (header) || UNW_FLAG_EHANDLER (header));
96 1.1 mrg }
97 1.1 mrg
98 1.1 mrg /* An OSSD block is there for IVMS_MODE == 3 only. */
99 1.1 mrg if (UNW_IVMS_MODE (header) != 3)
100 1.1 mrg return 0;
101 1.1 mrg
102 1.1 mrg /* The OSSD block is found past the header, unwind descriptor area
103 1.1 mrg and condition handler pointer, if any. */
104 1.1 mrg ossd = (ossddef *)
105 1.1 mrg /* Beware: uqword pointer arithmetic below. */
106 1.1 mrg (unw_info_block
107 1.1 mrg + 1
108 1.1 mrg + UNW_LENGTH (header)
109 1.1 mrg + (UNW_FLAG_EHANDLER (header) || UNW_FLAG_EHANDLER (header)));
110 1.1 mrg
111 1.1 mrg /* "A General Information segment may be omitted if all of its fields
112 1.1 mrg would have their default values. If a General Information segment
113 1.1 mrg is present, it must be the first in the OSSD area." So ... */
114 1.1 mrg
115 1.1 mrg if (eh_debug)
116 1.1 mrg printf ("ossd @ 0x%p\n", ossd);
117 1.1 mrg
118 1.1 mrg if (eh_debug && ossd->ossd$v_type == OSSD$K_GENERAL_INFO)
119 1.1 mrg printf ("exc_frame = %d - bot_frame = %d - base_frame = %d\n",
120 1.1 mrg ossd->ossd$v_exception_frame,
121 1.1 mrg ossd->ossd$v_bottom_of_stack,
122 1.1 mrg ossd->ossd$v_base_frame);
123 1.1 mrg
124 1.1 mrg return
125 1.1 mrg ossd->ossd$v_type == OSSD$K_GENERAL_INFO
126 1.1 mrg && (ossd->ossd$v_exception_frame
127 1.1 mrg || ossd->ossd$v_bottom_of_stack || ossd->ossd$v_base_frame);
128 1.1 mrg }
129 1.1 mrg
130 1.1 mrg /* Return a pointer to the unwind table entry for the function
131 1.1 mrg containing PC, 0 if we cannot find an entry or if the one we find
132 1.1 mrg calls for fallback processing. */
133 1.1 mrg
134 1.1 mrg struct unw_table_entry *
135 1.1 mrg _Unwind_FindTableEntry (void *pc, unw_word *segment_base,
136 1.1 mrg unw_word *gp, struct unw_table_entry *ent)
137 1.1 mrg {
138 1.1 mrg vms_unw_table_entry vueblock;
139 1.1 mrg
140 1.1 mrg if (SYS$GET_UNWIND_ENTRY_INFO (pc, &vueblock, 0) != SS$_NORMAL)
141 1.1 mrg return 0;
142 1.1 mrg
143 1.1 mrg /* If there is no unwind information, use fallback. */
144 1.1 mrg if (vueblock.info_offset == 0)
145 1.1 mrg return 0;
146 1.1 mrg
147 1.1 mrg /* If we need to force fallback processing, just pretend there is
148 1.1 mrg no entry. */
149 1.1 mrg if (force_fallback_processing_for (pc, &vueblock))
150 1.1 mrg return 0;
151 1.1 mrg
152 1.1 mrg *segment_base = 0; /* ??? Fixme. ??? */
153 1.1 mrg *gp = vueblock.gp_value;
154 1.1 mrg ent->start_offset = vueblock.start_offset;
155 1.1 mrg ent->end_offset = vueblock.end_offset;
156 1.1 mrg ent->info_offset = vueblock.info_offset;
157 1.1 mrg
158 1.1 mrg return ent;
159 1.1 mrg }
160