1 /* Native-dependent code for X86 BSD's. 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 "inferior.h" 22 #include "gdbthread.h" 23 24 /* We include <signal.h> to make sure `struct fxsave64' is defined on 25 NetBSD, since NetBSD's <machine/reg.h> needs it. */ 26 #include <signal.h> 27 #include <sys/types.h> 28 #include <sys/ptrace.h> 29 #include <machine/reg.h> 30 31 #include "x86-nat.h" 32 #include "x86-bsd-nat.h" 33 #include "inf-ptrace.h" 34 35 36 static PTRACE_TYPE_RET 37 gdb_ptrace (PTRACE_TYPE_ARG1 request, ptid_t ptid, PTRACE_TYPE_ARG3 addr) 38 { 39 #ifdef __NetBSD__ 40 /* Support for NetBSD threads: unlike other ptrace implementations in this 41 file, NetBSD requires that we pass both the pid and lwp. */ 42 return ptrace (request, ptid.pid (), addr, ptid.lwp ()); 43 #else 44 pid_t pid = get_ptrace_pid (ptid); 45 return ptrace (request, pid, addr, 0); 46 #endif 47 } 48 49 #ifdef PT_GETXSTATE_INFO 50 size_t x86bsd_xsave_len; 51 #endif 52 53 /* Support for debug registers. */ 54 55 #ifdef HAVE_PT_GETDBREGS 56 57 /* Helper macro to access debug register X. FreeBSD/amd64 and modern 58 versions of FreeBSD/i386 provide this macro in system headers. Define 59 a local version for systems that do not provide it. */ 60 #ifndef DBREG_DRX 61 #ifdef __NetBSD__ 62 #define DBREG_DRX(d, x) ((d)->dr[x]) 63 #else 64 #define DBREG_DRX(d, x) ((&d->dr0)[x]) 65 #endif 66 #endif 67 68 static unsigned long 69 x86bsd_dr_get (ptid_t ptid, int regnum) 70 { 71 struct dbreg dbregs; 72 73 if (gdb_ptrace (PT_GETDBREGS, ptid, (PTRACE_TYPE_ARG3) &dbregs) == -1) 74 perror_with_name (_("Couldn't read debug registers")); 75 76 return DBREG_DRX ((&dbregs), regnum); 77 } 78 79 static void 80 x86bsd_dr_set (ptid_t ptid, int regnum, unsigned long value) 81 { 82 struct dbreg dbregs; 83 84 if (gdb_ptrace (PT_GETDBREGS, ptid, (PTRACE_TYPE_ARG3) &dbregs) == -1) 85 perror_with_name (_("Couldn't get debug registers")); 86 87 /* For some mysterious reason, some of the reserved bits in the 88 debug control register get set. Mask these off, otherwise the 89 ptrace call below will fail. */ 90 DBREG_DRX ((&dbregs), 7) &= ~(0xffffffff0000fc00); 91 92 DBREG_DRX ((&dbregs), regnum) = value; 93 94 for (thread_info *thread : current_inferior ()->non_exited_threads ()) 95 { 96 if (gdb_ptrace (PT_SETDBREGS, thread->ptid, 97 (PTRACE_TYPE_ARG3) &dbregs) == -1) 98 perror_with_name (_("Couldn't write debug registers")); 99 } 100 } 101 102 static void 103 x86bsd_dr_set_control (unsigned long control) 104 { 105 x86bsd_dr_set (inferior_ptid, 7, control); 106 } 107 108 static void 109 x86bsd_dr_set_addr (int regnum, CORE_ADDR addr) 110 { 111 gdb_assert (regnum >= 0 && regnum <= 4); 112 113 x86bsd_dr_set (inferior_ptid, regnum, addr); 114 } 115 116 static CORE_ADDR 117 x86bsd_dr_get_addr (int regnum) 118 { 119 return x86bsd_dr_get (inferior_ptid, regnum); 120 } 121 122 static unsigned long 123 x86bsd_dr_get_status (void) 124 { 125 return x86bsd_dr_get (inferior_ptid, 6); 126 } 127 128 static unsigned long 129 x86bsd_dr_get_control (void) 130 { 131 return x86bsd_dr_get (inferior_ptid, 7); 132 } 133 134 #endif /* PT_GETDBREGS */ 135 136 void _initialize_x86_bsd_nat (); 137 void 138 _initialize_x86_bsd_nat () 139 { 140 #ifdef HAVE_PT_GETDBREGS 141 x86_dr_low.set_control = x86bsd_dr_set_control; 142 x86_dr_low.set_addr = x86bsd_dr_set_addr; 143 x86_dr_low.get_addr = x86bsd_dr_get_addr; 144 x86_dr_low.get_status = x86bsd_dr_get_status; 145 x86_dr_low.get_control = x86bsd_dr_get_control; 146 x86_set_debug_register_length (sizeof (void *)); 147 #endif /* HAVE_PT_GETDBREGS */ 148 } 149