1/* Target-dependent code for OpenBSD/amd64. 2 3 Copyright (C) 2003-2020 Free Software Foundation, Inc. 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 9 the Free Software Foundation; either version 3 of the License, or 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 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "frame.h" 22#include "frame-unwind.h" 23#include "gdbcore.h" 24#include "symtab.h" 25#include "objfiles.h" 26#include "osabi.h" 27#include "regcache.h" 28#include "regset.h" 29#include "target.h" 30#include "trad-frame.h" 31 32#include "obsd-tdep.h" 33#include "amd64-tdep.h" 34#include "i387-tdep.h" 35#include "gdbsupport/x86-xstate.h" 36#include "solib-svr4.h" 37#include "bsd-uthread.h" 38 39/* Support for signal handlers. */ 40 41/* Default page size. */ 42static const int amd64obsd_page_size = 4096; 43 44/* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp 45 routine. */ 46 47static int 48amd64obsd_sigtramp_p (struct frame_info *this_frame) 49{ 50 CORE_ADDR pc = get_frame_pc (this_frame); 51 CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1)); 52 const gdb_byte osigreturn[] = 53 { 54 0x48, 0xc7, 0xc0, 55 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */ 56 0xcd, 0x80 /* int $0x80 */ 57 }; 58 const gdb_byte sigreturn[] = 59 { 60 0x48, 0xc7, 0xc0, 61 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */ 62 0x0f, 0x05 /* syscall */ 63 }; 64 size_t buflen = (sizeof sigreturn) + 1; 65 gdb_byte *buf; 66 const char *name; 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; 73 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) 77 return 0; 78 79 /* If we can't read the instructions at START_PC, return zero. */ 80 buf = (gdb_byte *) alloca ((sizeof sigreturn) + 1); 81 if (!safe_frame_unwind_memory (this_frame, start_pc + 6, buf, buflen)) 82 return 0; 83 84 /* Check for sigreturn(2). Depending on how the assembler encoded 85 the `movq %rsp, %rdi' instruction, the code starts at offset 6 or 86 7. OpenBSD 5.0 and later use the `syscall' instruction. Older 87 versions use `int $0x80'. Check for both. */ 88 if (memcmp (buf, sigreturn, sizeof sigreturn) 89 && memcmp (buf + 1, sigreturn, sizeof sigreturn) 90 && memcmp (buf, osigreturn, sizeof osigreturn) 91 && memcmp (buf + 1, osigreturn, sizeof osigreturn)) 92 return 0; 93 94 return 1; 95} 96 97/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the 98 address of the associated sigcontext structure. */ 99 100static CORE_ADDR 101amd64obsd_sigcontext_addr (struct frame_info *this_frame) 102{ 103 CORE_ADDR pc = get_frame_pc (this_frame); 104 ULONGEST offset = (pc & (amd64obsd_page_size - 1)); 105 106 /* The %rsp register points at `struct sigcontext' upon entry of a 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 118 if (offset > 5) 119 return get_frame_register_unsigned (this_frame, AMD64_RDI_REGNUM); 120 else 121 return get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); 122} 123 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 129/* From <machine/reg.h>. */ 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 */ 140 4 * 8, /* %r8 .. */ 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 158/* From <machine/signal.h>. */ 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 */ 169 4 * 8, /* %r8 ... */ 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 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 */ 198 12 * 8, /* %r8 ... */ 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{ 224 struct gdbarch *gdbarch = regcache->arch (); 225 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 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. */ 238 sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); 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; 243 store_unsigned_integer (buf, 8, byte_order, sp + offset); 244 regcache->raw_supply (AMD64_RSP_REGNUM, buf); 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) 255 sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); 256 257 /* Read the saved register from the stack frame. */ 258 read_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8); 259 regcache->raw_supply (i, buf); 260 } 261 } 262} 263 264static void 265amd64obsd_collect_uthread (const struct regcache *regcache, 266 int regnum, CORE_ADDR addr) 267{ 268 struct gdbarch *gdbarch = regcache->arch (); 269 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 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; 284 regcache->raw_collect (AMD64_RSP_REGNUM, buf); 285 sp = extract_unsigned_integer (buf, 8, byte_order) - offset; 286 287 /* Store the stack pointer. */ 288 write_memory_unsigned_integer (sp_addr, 8, byte_order, sp); 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) 303 sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); 304 305 /* Write the register into the stack frame. */ 306 regcache->raw_collect (i, buf); 307 write_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8); 308 } 309 } 310} 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 * 318amd64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) 319{ 320 struct gdbarch *gdbarch = get_frame_arch (this_frame); 321 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 322 struct trad_frame_cache *cache; 323 CORE_ADDR func, sp, addr; 324 ULONGEST cs; 325 const char *name; 326 int i; 327 328 if (*this_cache) 329 return (struct trad_frame_cache *) *this_cache; 330 331 cache = trad_frame_cache_zalloc (this_frame); 332 *this_cache = cache; 333 334 func = get_frame_func (this_frame); 335 sp = get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); 336 337 find_pc_partial_function (func, &name, NULL, NULL); 338 if (name && startswith (name, "Xintr")) 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. */ 348 addr += amd64obsd_tf_reg_offset[AMD64_CS_REGNUM]; 349 cs = read_memory_unsigned_integer (addr, 8, byte_order); 350 if ((cs & I386_SEL_RPL) == I386_SEL_UPL) 351 { 352 /* Trap from user space; terminate backtrace. */ 353 trad_frame_set_id (cache, outer_frame_id); 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 365amd64obsd_trapframe_this_id (struct frame_info *this_frame, 366 void **this_cache, struct frame_id *this_id) 367{ 368 struct trad_frame_cache *cache = 369 amd64obsd_trapframe_cache (this_frame, this_cache); 370 371 trad_frame_get_id (cache, this_id); 372} 373 374static struct value * 375amd64obsd_trapframe_prev_register (struct frame_info *this_frame, 376 void **this_cache, int regnum) 377{ 378 struct trad_frame_cache *cache = 379 amd64obsd_trapframe_cache (this_frame, this_cache); 380 381 return trad_frame_get_register (cache, this_frame, regnum); 382} 383 384static int 385amd64obsd_trapframe_sniffer (const struct frame_unwind *self, 386 struct frame_info *this_frame, 387 void **this_prologue_cache) 388{ 389 ULONGEST cs; 390 const char *name; 391 392 /* Check Current Privilege Level and bail out if we're not executing 393 in kernel space. */ 394 cs = get_frame_register_unsigned (this_frame, AMD64_CS_REGNUM); 395 if ((cs & I386_SEL_RPL) == I386_SEL_UPL) 396 return 0; 397 398 find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL); 399 return (name && ((strcmp (name, "calltrap") == 0) 400 || (strcmp (name, "osyscall1") == 0) 401 || (strcmp (name, "Xsyscall") == 0) 402 || (startswith (name, "Xintr")))); 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, 410 default_frame_unwind_stop_reason, 411 amd64obsd_trapframe_this_id, 412 amd64obsd_trapframe_prev_register, 413 NULL, 414 amd64obsd_trapframe_sniffer 415}; 416 417 418static void 419amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 420{ 421 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 422 423 amd64_init_abi (info, gdbarch, 424 amd64_target_description (X86_XSTATE_SSE_MASK, true)); 425 obsd_init_abi (info, gdbarch); 426 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 432 tdep->jb_pc_offset = 7 * 8; 433 434 tdep->sigtramp_p = amd64obsd_sigtramp_p; 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); 438 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 443 /* OpenBSD uses SVR4-style shared libraries. */ 444 set_solib_svr4_fetch_link_map_offsets 445 (gdbarch, svr4_lp64_fetch_link_map_offsets); 446 447 /* Unwind kernel trap frames correctly. */ 448 frame_unwind_prepend_unwinder (gdbarch, &amd64obsd_trapframe_unwind); 449} 450 451void _initialize_amd64obsd_tdep (); 452void 453_initialize_amd64obsd_tdep () 454{ 455 /* The OpenBSD/amd64 native dependent code makes this assumption. */ 456 gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == AMD64_NUM_GREGS); 457 458 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, 459 GDB_OSABI_OPENBSD, amd64obsd_init_abi); 460} 461