]>
Commit | Line | Data |
---|---|---|
cfaf379b MK |
1 | /* Target-dependent code for OpenBSD/vax. |
2 | ||
7b6bb8da JB |
3 | Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 |
4 | Free Software Foundation, Inc. | |
cfaf379b MK |
5 | |
6 | This file is part of GDB. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
a9762ec7 | 10 | the Free Software Foundation; either version 3 of the License, or |
cfaf379b MK |
11 | (at your option) any later version. |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
a9762ec7 | 19 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
cfaf379b MK |
20 | |
21 | #include "defs.h" | |
22 | #include "arch-utils.h" | |
23 | #include "frame.h" | |
24 | #include "frame-unwind.h" | |
25 | #include "osabi.h" | |
26 | #include "symtab.h" | |
27 | #include "trad-frame.h" | |
28 | ||
29 | #include "vax-tdep.h" | |
30 | ||
31 | #include "gdb_string.h" | |
32 | ||
33 | /* Signal trampolines. */ | |
34 | ||
35 | /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page | |
36 | in virtual memory. The randomness makes it somewhat tricky to | |
37 | detect it, but fortunately we can rely on the fact that the start | |
38 | of the sigtramp routine is page-aligned. We recognize the | |
39 | trampoline by looking for the code that invokes the sigreturn | |
40 | system call. The offset where we can find that code varies from | |
41 | release to release. | |
42 | ||
43 | By the way, the mapping mentioned above is read-only, so you cannot | |
44 | place a breakpoint in the signal trampoline. */ | |
45 | ||
46 | /* Default page size. */ | |
47 | static const int vaxobsd_page_size = 4096; | |
48 | ||
49 | /* Offset for sigreturn(2). */ | |
50 | static const int vaxobsd_sigreturn_offset = 0x11; | |
51 | ||
52 | /* Instruction sequence for sigreturn(2). VAX doesn't have | |
53 | fixed-length instructions so we include the ensuing exit(2) to | |
54 | reduce the chance of spurious matches. */ | |
55 | static const gdb_byte vaxobsd_sigreturn[] = { | |
56 | 0xbc, 0x8f, 0x67, 0x00, /* chmk $SYS_sigreturn */ | |
57 | 0xbc, 0x01 /* chmk $SYS_exit */ | |
58 | }; | |
59 | ||
60 | static int | |
94afd7a6 UW |
61 | vaxobsd_sigtramp_sniffer (const struct frame_unwind *self, |
62 | struct frame_info *this_frame, | |
63 | void **this_cache) | |
cfaf379b | 64 | { |
94afd7a6 | 65 | CORE_ADDR pc = get_frame_pc (this_frame); |
cfaf379b MK |
66 | CORE_ADDR start_pc = (pc & ~(vaxobsd_page_size - 1)); |
67 | CORE_ADDR sigreturn_addr = start_pc + vaxobsd_sigreturn_offset; | |
68 | gdb_byte *buf; | |
69 | char *name; | |
70 | ||
71 | find_pc_partial_function (pc, &name, NULL, NULL); | |
72 | if (name) | |
73 | return 0; | |
74 | ||
75 | buf = alloca(sizeof vaxobsd_sigreturn); | |
94afd7a6 | 76 | if (!safe_frame_unwind_memory (this_frame, sigreturn_addr, |
cfaf379b MK |
77 | buf, sizeof vaxobsd_sigreturn)) |
78 | return 0; | |
79 | ||
80 | if (memcmp(buf, vaxobsd_sigreturn, sizeof vaxobsd_sigreturn) == 0) | |
81 | return 1; | |
82 | ||
83 | return 0; | |
84 | } | |
85 | ||
86 | static struct trad_frame_cache * | |
94afd7a6 | 87 | vaxobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) |
cfaf379b MK |
88 | { |
89 | struct trad_frame_cache *cache; | |
90 | CORE_ADDR addr, base, func; | |
91 | ||
92 | if (*this_cache) | |
93 | return *this_cache; | |
94 | ||
94afd7a6 | 95 | cache = trad_frame_cache_zalloc (this_frame); |
cfaf379b MK |
96 | *this_cache = cache; |
97 | ||
94afd7a6 | 98 | func = get_frame_pc (this_frame); |
cfaf379b MK |
99 | func &= ~(vaxobsd_page_size - 1); |
100 | ||
94afd7a6 UW |
101 | base = get_frame_register_unsigned (this_frame, VAX_SP_REGNUM); |
102 | addr = get_frame_memory_unsigned (this_frame, base - 4, 4); | |
cfaf379b MK |
103 | |
104 | trad_frame_set_reg_addr (cache, VAX_SP_REGNUM, addr + 8); | |
105 | trad_frame_set_reg_addr (cache, VAX_FP_REGNUM, addr + 12); | |
106 | trad_frame_set_reg_addr (cache, VAX_AP_REGNUM, addr + 16); | |
107 | trad_frame_set_reg_addr (cache, VAX_PC_REGNUM, addr + 20); | |
108 | trad_frame_set_reg_addr (cache, VAX_PS_REGNUM, addr + 24); | |
109 | ||
110 | /* Construct the frame ID using the function start. */ | |
111 | trad_frame_set_id (cache, frame_id_build (base, func)); | |
112 | ||
113 | return cache; | |
114 | } | |
115 | ||
116 | static void | |
94afd7a6 | 117 | vaxobsd_sigtramp_frame_this_id (struct frame_info *this_frame, |
cfaf379b MK |
118 | void **this_cache, struct frame_id *this_id) |
119 | { | |
120 | struct trad_frame_cache *cache = | |
94afd7a6 | 121 | vaxobsd_sigtramp_frame_cache (this_frame, this_cache); |
cfaf379b MK |
122 | |
123 | trad_frame_get_id (cache, this_id); | |
124 | } | |
125 | ||
94afd7a6 UW |
126 | static struct value * |
127 | vaxobsd_sigtramp_frame_prev_register (struct frame_info *this_frame, | |
128 | void **this_cache, int regnum) | |
cfaf379b MK |
129 | { |
130 | struct trad_frame_cache *cache = | |
94afd7a6 | 131 | vaxobsd_sigtramp_frame_cache (this_frame, this_cache); |
cfaf379b | 132 | |
94afd7a6 | 133 | return trad_frame_get_register (cache, this_frame, regnum); |
cfaf379b MK |
134 | } |
135 | ||
136 | static const struct frame_unwind vaxobsd_sigtramp_frame_unwind = { | |
137 | SIGTRAMP_FRAME, | |
8fbca658 | 138 | default_frame_unwind_stop_reason, |
cfaf379b | 139 | vaxobsd_sigtramp_frame_this_id, |
94afd7a6 UW |
140 | vaxobsd_sigtramp_frame_prev_register, |
141 | NULL, | |
142 | vaxobsd_sigtramp_sniffer | |
cfaf379b | 143 | }; |
cfaf379b MK |
144 | \f |
145 | ||
146 | /* OpenBSD a.out. */ | |
147 | ||
148 | static void | |
149 | vaxobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
150 | { | |
94afd7a6 | 151 | frame_unwind_append_unwinder (gdbarch, &vaxobsd_sigtramp_frame_unwind); |
cfaf379b MK |
152 | } |
153 | ||
154 | /* FIXME: kettenis/20050821: Since OpenBSD/vax binaries are | |
155 | indistingushable from NetBSD/vax a.out binaries, building a GDB | |
156 | that should support both these targets will probably not work as | |
157 | expected. */ | |
158 | #define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT | |
159 | ||
160 | static enum gdb_osabi | |
161 | vaxobsd_aout_osabi_sniffer (bfd *abfd) | |
162 | { | |
163 | if (strcmp (bfd_get_target (abfd), "a.out-vax-netbsd") == 0) | |
164 | return GDB_OSABI_OPENBSD_AOUT; | |
165 | ||
166 | return GDB_OSABI_UNKNOWN; | |
167 | } | |
168 | \f | |
169 | ||
170 | /* Provide a prototype to silence -Wmissing-prototypes. */ | |
171 | void _initialize_vaxobsd_tdep (void); | |
172 | ||
173 | void | |
174 | _initialize_vaxobsd_tdep (void) | |
175 | { | |
176 | gdbarch_register_osabi_sniffer (bfd_arch_vax, bfd_target_aout_flavour, | |
177 | vaxobsd_aout_osabi_sniffer); | |
178 | ||
179 | gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_OPENBSD_AOUT, | |
180 | vaxobsd_init_abi); | |
181 | } |