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