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