gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / amd64-obsd-tdep.c
CommitLineData
e2879ccb
MK
1/* Target-dependent code for OpenBSD/amd64.
2
b811d2c2 3 Copyright (C) 2003-2020 Free Software Foundation, Inc.
e2879ccb
MK
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
e2879ccb
MK
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
e2879ccb
MK
19
20#include "defs.h"
d55e5aa6 21#include "frame.h"
4de283e4 22#include "frame-unwind.h"
e2879ccb 23#include "gdbcore.h"
4de283e4 24#include "symtab.h"
911bc6ee 25#include "objfiles.h"
e2879ccb 26#include "osabi.h"
d78749b4 27#include "regcache.h"
30b344b1 28#include "regset.h"
e2879ccb 29#include "target.h"
f6acec62 30#include "trad-frame.h"
e2879ccb 31
4de283e4
TT
32#include "obsd-tdep.h"
33#include "amd64-tdep.h"
34#include "i387-tdep.h"
268a13a5 35#include "gdbsupport/x86-xstate.h"
4de283e4
TT
36#include "solib-svr4.h"
37#include "bsd-uthread.h"
38
e2879ccb
MK
39/* Support for signal handlers. */
40
911bc6ee 41/* Default page size. */
e2879ccb
MK
42static const int amd64obsd_page_size = 4096;
43
10458914
DJ
44/* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp
45 routine. */
911bc6ee 46
e2879ccb 47static int
10458914 48amd64obsd_sigtramp_p (struct frame_info *this_frame)
e2879ccb 49{
10458914 50 CORE_ADDR pc = get_frame_pc (this_frame);
e2879ccb 51 CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1));
0dcddd84 52 const gdb_byte osigreturn[] =
e2879ccb
MK
53 {
54 0x48, 0xc7, 0xc0,
55 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
84d04465 56 0xcd, 0x80 /* int $0x80 */
e2879ccb 57 };
0dcddd84
MK
58 const gdb_byte sigreturn[] =
59 {
60 0x48, 0xc7, 0xc0,
61 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
62 0x0f, 0x05 /* syscall */
63 };
1c5bf419 64 size_t buflen = (sizeof sigreturn) + 1;
d8de1ef7 65 gdb_byte *buf;
2c02bd72 66 const char *name;
911bc6ee
MK
67
68 /* If the function has a valid symbol name, it isn't a
69 trampoline. */
70 find_pc_partial_function (pc, &name, NULL, NULL);
71 if (name != NULL)
72 return 0;
e2879ccb 73
911bc6ee
MK
74 /* If the function lives in a valid section (even without a starting
75 point) it isn't a trampoline. */
76 if (find_pc_section (pc) != NULL)
e2879ccb
MK
77 return 0;
78
79 /* If we can't read the instructions at START_PC, return zero. */
224c3ddb 80 buf = (gdb_byte *) alloca ((sizeof sigreturn) + 1);
10458914 81 if (!safe_frame_unwind_memory (this_frame, start_pc + 6, buf, buflen))
e2879ccb
MK
82 return 0;
83
4cd28409
MK
84 /* Check for sigreturn(2). Depending on how the assembler encoded
85 the `movq %rsp, %rdi' instruction, the code starts at offset 6 or
0dcddd84
MK
86 7. OpenBSD 5.0 and later use the `syscall' instruction. Older
87 versions use `int $0x80'. Check for both. */
4cd28409 88 if (memcmp (buf, sigreturn, sizeof sigreturn)
0dcddd84
MK
89 && memcmp (buf + 1, sigreturn, sizeof sigreturn)
90 && memcmp (buf, osigreturn, sizeof osigreturn)
91 && memcmp (buf + 1, osigreturn, sizeof osigreturn))
e2879ccb
MK
92 return 0;
93
94 return 1;
95}
96
10458914
DJ
97/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the
98 address of the associated sigcontext structure. */
e2879ccb
MK
99
100static CORE_ADDR
10458914 101amd64obsd_sigcontext_addr (struct frame_info *this_frame)
e2879ccb 102{
10458914 103 CORE_ADDR pc = get_frame_pc (this_frame);
0fe85704
MK
104 ULONGEST offset = (pc & (amd64obsd_page_size - 1));
105
e2879ccb 106 /* The %rsp register points at `struct sigcontext' upon entry of a
0fe85704
MK
107 signal trampoline. The relevant part of the trampoline is
108
109 call *%rax
110 movq %rsp, %rdi
111 pushq %rdi
112 movq $SYS_sigreturn,%rax
113 int $0x80
114
115 (see /usr/src/sys/arch/amd64/amd64/locore.S). The `pushq'
116 instruction clobbers %rsp, but its value is saved in `%rdi'. */
117
4cd28409 118 if (offset > 5)
10458914 119 return get_frame_register_unsigned (this_frame, AMD64_RDI_REGNUM);
0fe85704 120 else
10458914 121 return get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM);
e2879ccb
MK
122}
123\f
124/* OpenBSD 3.5 or later. */
125
126/* Mapping between the general-purpose registers in `struct reg'
127 format and GDB's register cache layout. */
128
30b344b1 129/* From <machine/reg.h>. */
e2879ccb
MK
130int amd64obsd_r_reg_offset[] =
131{
132 14 * 8, /* %rax */
133 13 * 8, /* %rbx */
134 3 * 8, /* %rcx */
135 2 * 8, /* %rdx */
136 1 * 8, /* %rsi */
137 0 * 8, /* %rdi */
138 12 * 8, /* %rbp */
139 15 * 8, /* %rsp */
0963b4bd 140 4 * 8, /* %r8 .. */
e2879ccb
MK
141 5 * 8,
142 6 * 8,
143 7 * 8,
144 8 * 8,
145 9 * 8,
146 10 * 8,
147 11 * 8, /* ... %r15 */
148 16 * 8, /* %rip */
149 17 * 8, /* %eflags */
150 18 * 8, /* %cs */
151 19 * 8, /* %ss */
152 20 * 8, /* %ds */
153 21 * 8, /* %es */
154 22 * 8, /* %fs */
155 23 * 8 /* %gs */
156};
157
30b344b1 158/* From <machine/signal.h>. */
e2879ccb
MK
159static int amd64obsd_sc_reg_offset[] =
160{
161 14 * 8, /* %rax */
162 13 * 8, /* %rbx */
163 3 * 8, /* %rcx */
164 2 * 8, /* %rdx */
165 1 * 8, /* %rsi */
166 0 * 8, /* %rdi */
167 12 * 8, /* %rbp */
168 24 * 8, /* %rsp */
0963b4bd 169 4 * 8, /* %r8 ... */
e2879ccb
MK
170 5 * 8,
171 6 * 8,
172 7 * 8,
173 8 * 8,
174 9 * 8,
175 10 * 8,
176 11 * 8, /* ... %r15 */
177 21 * 8, /* %rip */
178 23 * 8, /* %eflags */
179 22 * 8, /* %cs */
180 25 * 8, /* %ss */
181 18 * 8, /* %ds */
182 17 * 8, /* %es */
183 16 * 8, /* %fs */
184 15 * 8 /* %gs */
185};
186
d78749b4
MK
187/* From /usr/src/lib/libpthread/arch/amd64/uthread_machdep.c. */
188static int amd64obsd_uthread_reg_offset[] =
189{
190 19 * 8, /* %rax */
191 16 * 8, /* %rbx */
192 18 * 8, /* %rcx */
193 17 * 8, /* %rdx */
194 14 * 8, /* %rsi */
195 13 * 8, /* %rdi */
196 15 * 8, /* %rbp */
197 -1, /* %rsp */
0963b4bd 198 12 * 8, /* %r8 ... */
d78749b4
MK
199 11 * 8,
200 10 * 8,
201 9 * 8,
202 8 * 8,
203 7 * 8,
204 6 * 8,
205 5 * 8, /* ... %r15 */
206 20 * 8, /* %rip */
207 4 * 8, /* %eflags */
208 21 * 8, /* %cs */
209 -1, /* %ss */
210 3 * 8, /* %ds */
211 2 * 8, /* %es */
212 1 * 8, /* %fs */
213 0 * 8 /* %gs */
214};
215
216/* Offset within the thread structure where we can find the saved
217 stack pointer (%esp). */
218#define AMD64OBSD_UTHREAD_RSP_OFFSET 400
219
220static void
221amd64obsd_supply_uthread (struct regcache *regcache,
222 int regnum, CORE_ADDR addr)
223{
ac7936df 224 struct gdbarch *gdbarch = regcache->arch ();
e17a4113 225 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
d78749b4
MK
226 CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET;
227 CORE_ADDR sp = 0;
228 gdb_byte buf[8];
229 int i;
230
231 gdb_assert (regnum >= -1);
232
233 if (regnum == -1 || regnum == AMD64_RSP_REGNUM)
234 {
235 int offset;
236
237 /* Fetch stack pointer from thread structure. */
e17a4113 238 sp = read_memory_unsigned_integer (sp_addr, 8, byte_order);
d78749b4
MK
239
240 /* Adjust the stack pointer such that it looks as if we just
241 returned from _thread_machdep_switch. */
242 offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8;
e17a4113 243 store_unsigned_integer (buf, 8, byte_order, sp + offset);
73e1c03f 244 regcache->raw_supply (AMD64_RSP_REGNUM, buf);
d78749b4
MK
245 }
246
247 for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++)
248 {
249 if (amd64obsd_uthread_reg_offset[i] != -1
250 && (regnum == -1 || regnum == i))
251 {
252 /* Fetch stack pointer from thread structure (if we didn't
253 do so already). */
254 if (sp == 0)
e17a4113 255 sp = read_memory_unsigned_integer (sp_addr, 8, byte_order);
d78749b4
MK
256
257 /* Read the saved register from the stack frame. */
258 read_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8);
73e1c03f 259 regcache->raw_supply (i, buf);
d78749b4
MK
260 }
261 }
262}
263
264static void
265amd64obsd_collect_uthread (const struct regcache *regcache,
266 int regnum, CORE_ADDR addr)
267{
ac7936df 268 struct gdbarch *gdbarch = regcache->arch ();
e17a4113 269 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
d78749b4
MK
270 CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET;
271 CORE_ADDR sp = 0;
272 gdb_byte buf[8];
273 int i;
274
275 gdb_assert (regnum >= -1);
276
277 if (regnum == -1 || regnum == AMD64_RSP_REGNUM)
278 {
279 int offset;
280
281 /* Calculate the stack pointer (frame pointer) that will be
282 stored into the thread structure. */
283 offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8;
34a79281 284 regcache->raw_collect (AMD64_RSP_REGNUM, buf);
e17a4113 285 sp = extract_unsigned_integer (buf, 8, byte_order) - offset;
d78749b4
MK
286
287 /* Store the stack pointer. */
e17a4113 288 write_memory_unsigned_integer (sp_addr, 8, byte_order, sp);
d78749b4
MK
289
290 /* The stack pointer was (potentially) modified. Make sure we
291 build a proper stack frame. */
292 regnum = -1;
293 }
294
295 for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++)
296 {
297 if (amd64obsd_uthread_reg_offset[i] != -1
298 && (regnum == -1 || regnum == i))
299 {
300 /* Fetch stack pointer from thread structure (if we didn't
301 calculate it already). */
302 if (sp == 0)
e17a4113 303 sp = read_memory_unsigned_integer (sp_addr, 8, byte_order);
d78749b4
MK
304
305 /* Write the register into the stack frame. */
34a79281 306 regcache->raw_collect (i, buf);
d78749b4
MK
307 write_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8);
308 }
309 }
310}
f6acec62
MK
311/* Kernel debugging support. */
312
313/* From <machine/frame.h>. Easy since `struct trapframe' matches
314 `struct sigcontext'. */
315#define amd64obsd_tf_reg_offset amd64obsd_sc_reg_offset
316
317static struct trad_frame_cache *
10458914 318amd64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache)
f6acec62 319{
e17a4113
UW
320 struct gdbarch *gdbarch = get_frame_arch (this_frame);
321 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
f6acec62
MK
322 struct trad_frame_cache *cache;
323 CORE_ADDR func, sp, addr;
324 ULONGEST cs;
2c02bd72 325 const char *name;
f6acec62
MK
326 int i;
327
328 if (*this_cache)
9a3c8263 329 return (struct trad_frame_cache *) *this_cache;
f6acec62 330
10458914 331 cache = trad_frame_cache_zalloc (this_frame);
f6acec62
MK
332 *this_cache = cache;
333
10458914
DJ
334 func = get_frame_func (this_frame);
335 sp = get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM);
f6acec62
MK
336
337 find_pc_partial_function (func, &name, NULL, NULL);
61012eef 338 if (name && startswith (name, "Xintr"))
f6acec62
MK
339 addr = sp + 8; /* It's an interrupt frame. */
340 else
341 addr = sp;
342
343 for (i = 0; i < ARRAY_SIZE (amd64obsd_tf_reg_offset); i++)
344 if (amd64obsd_tf_reg_offset[i] != -1)
345 trad_frame_set_reg_addr (cache, i, addr + amd64obsd_tf_reg_offset[i]);
346
347 /* Read %cs from trap frame. */
7238f002 348 addr += amd64obsd_tf_reg_offset[AMD64_CS_REGNUM];
e17a4113 349 cs = read_memory_unsigned_integer (addr, 8, byte_order);
f6acec62
MK
350 if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
351 {
6d566cff 352 /* Trap from user space; terminate backtrace. */
005ca36a 353 trad_frame_set_id (cache, outer_frame_id);
f6acec62
MK
354 }
355 else
356 {
357 /* Construct the frame ID using the function start. */
358 trad_frame_set_id (cache, frame_id_build (sp + 16, func));
359 }
360
361 return cache;
362}
363
364static void
10458914 365amd64obsd_trapframe_this_id (struct frame_info *this_frame,
f6acec62
MK
366 void **this_cache, struct frame_id *this_id)
367{
368 struct trad_frame_cache *cache =
10458914 369 amd64obsd_trapframe_cache (this_frame, this_cache);
f6acec62
MK
370
371 trad_frame_get_id (cache, this_id);
372}
373
10458914
DJ
374static struct value *
375amd64obsd_trapframe_prev_register (struct frame_info *this_frame,
376 void **this_cache, int regnum)
f6acec62
MK
377{
378 struct trad_frame_cache *cache =
10458914 379 amd64obsd_trapframe_cache (this_frame, this_cache);
f6acec62 380
10458914 381 return trad_frame_get_register (cache, this_frame, regnum);
f6acec62
MK
382}
383
384static int
385amd64obsd_trapframe_sniffer (const struct frame_unwind *self,
10458914 386 struct frame_info *this_frame,
f6acec62
MK
387 void **this_prologue_cache)
388{
389 ULONGEST cs;
2c02bd72 390 const char *name;
f6acec62 391
e5cc6d11 392 /* Check Current Privilege Level and bail out if we're not executing
6d566cff 393 in kernel space. */
10458914 394 cs = get_frame_register_unsigned (this_frame, AMD64_CS_REGNUM);
f6acec62
MK
395 if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
396 return 0;
397
10458914 398 find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL);
f6acec62
MK
399 return (name && ((strcmp (name, "calltrap") == 0)
400 || (strcmp (name, "osyscall1") == 0)
401 || (strcmp (name, "Xsyscall") == 0)
61012eef 402 || (startswith (name, "Xintr"))));
f6acec62
MK
403}
404
405static const struct frame_unwind amd64obsd_trapframe_unwind = {
406 /* FIXME: kettenis/20051219: This really is more like an interrupt
407 frame, but SIGTRAMP_FRAME would print <signal handler called>,
408 which really is not what we want here. */
409 NORMAL_FRAME,
8fbca658 410 default_frame_unwind_stop_reason,
f6acec62
MK
411 amd64obsd_trapframe_this_id,
412 amd64obsd_trapframe_prev_register,
413 NULL,
414 amd64obsd_trapframe_sniffer
415};
416\f
d78749b4 417
e2879ccb
MK
418static void
419amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
420{
421 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
422
2434b019 423 amd64_init_abi (info, gdbarch,
41206e32 424 amd64_target_description (X86_XSTATE_SSE_MASK, true));
93ffa5b9 425 obsd_init_abi (info, gdbarch);
e2879ccb 426
30b344b1
MK
427 /* Initialize general-purpose register set details. */
428 tdep->gregset_reg_offset = amd64obsd_r_reg_offset;
429 tdep->gregset_num_regs = ARRAY_SIZE (amd64obsd_r_reg_offset);
430 tdep->sizeof_gregset = 24 * 8;
431
e2879ccb
MK
432 tdep->jb_pc_offset = 7 * 8;
433
911bc6ee 434 tdep->sigtramp_p = amd64obsd_sigtramp_p;
e2879ccb
MK
435 tdep->sigcontext_addr = amd64obsd_sigcontext_addr;
436 tdep->sc_reg_offset = amd64obsd_sc_reg_offset;
437 tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset);
7e654c37 438
d78749b4
MK
439 /* OpenBSD provides a user-level threads implementation. */
440 bsd_uthread_set_supply_uthread (gdbarch, amd64obsd_supply_uthread);
441 bsd_uthread_set_collect_uthread (gdbarch, amd64obsd_collect_uthread);
442
7e654c37
MK
443 /* OpenBSD uses SVR4-style shared libraries. */
444 set_solib_svr4_fetch_link_map_offsets
445 (gdbarch, svr4_lp64_fetch_link_map_offsets);
f6acec62
MK
446
447 /* Unwind kernel trap frames correctly. */
448 frame_unwind_prepend_unwinder (gdbarch, &amd64obsd_trapframe_unwind);
e2879ccb 449}
e2879ccb 450
6c265988 451void _initialize_amd64obsd_tdep ();
e2879ccb 452void
6c265988 453_initialize_amd64obsd_tdep ()
e2879ccb
MK
454{
455 /* The OpenBSD/amd64 native dependent code makes this assumption. */
90f90721 456 gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == AMD64_NUM_GREGS);
e2879ccb
MK
457
458 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
1736a7bd 459 GDB_OSABI_OPENBSD, amd64obsd_init_abi);
e2879ccb 460}
This page took 0.97546 seconds and 4 git commands to generate.