GDB (API)
|
00001 /* Native-dependent code for AMD64 BSD's. 00002 00003 Copyright (C) 2003-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "inferior.h" 00022 #include "regcache.h" 00023 #include "target.h" 00024 00025 /* We include <signal.h> to make sure `struct fxsave64' is defined on 00026 NetBSD, since NetBSD's <machine/reg.h> needs it. */ 00027 #include "gdb_assert.h" 00028 #include <signal.h> 00029 #include <sys/types.h> 00030 #include <sys/ptrace.h> 00031 #include <machine/reg.h> 00032 00033 #include "amd64-tdep.h" 00034 #include "amd64-nat.h" 00035 #include "amd64bsd-nat.h" 00036 #include "inf-ptrace.h" 00037 00038 00039 /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this 00040 for all registers (including the floating-point registers). */ 00041 00042 static void 00043 amd64bsd_fetch_inferior_registers (struct target_ops *ops, 00044 struct regcache *regcache, int regnum) 00045 { 00046 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00047 00048 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) 00049 { 00050 struct reg regs; 00051 00052 if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), 00053 (PTRACE_TYPE_ARG3) ®s, 0) == -1) 00054 perror_with_name (_("Couldn't get registers")); 00055 00056 amd64_supply_native_gregset (regcache, ®s, -1); 00057 if (regnum != -1) 00058 return; 00059 } 00060 00061 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) 00062 { 00063 struct fpreg fpregs; 00064 00065 if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), 00066 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 00067 perror_with_name (_("Couldn't get floating point status")); 00068 00069 amd64_supply_fxsave (regcache, -1, &fpregs); 00070 } 00071 } 00072 00073 /* Store register REGNUM back into the inferior. If REGNUM is -1, do 00074 this for all registers (including the floating-point registers). */ 00075 00076 static void 00077 amd64bsd_store_inferior_registers (struct target_ops *ops, 00078 struct regcache *regcache, int regnum) 00079 { 00080 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00081 00082 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) 00083 { 00084 struct reg regs; 00085 00086 if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), 00087 (PTRACE_TYPE_ARG3) ®s, 0) == -1) 00088 perror_with_name (_("Couldn't get registers")); 00089 00090 amd64_collect_native_gregset (regcache, ®s, regnum); 00091 00092 if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), 00093 (PTRACE_TYPE_ARG3) ®s, 0) == -1) 00094 perror_with_name (_("Couldn't write registers")); 00095 00096 if (regnum != -1) 00097 return; 00098 } 00099 00100 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) 00101 { 00102 struct fpreg fpregs; 00103 00104 if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), 00105 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 00106 perror_with_name (_("Couldn't get floating point status")); 00107 00108 amd64_collect_fxsave (regcache, regnum, &fpregs); 00109 00110 if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), 00111 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 00112 perror_with_name (_("Couldn't write floating point status")); 00113 } 00114 } 00115 00116 /* Create a prototype *BSD/amd64 target. The client can override it 00117 with local methods. */ 00118 00119 struct target_ops * 00120 amd64bsd_target (void) 00121 { 00122 struct target_ops *t; 00123 00124 t = inf_ptrace_target (); 00125 t->to_fetch_registers = amd64bsd_fetch_inferior_registers; 00126 t->to_store_registers = amd64bsd_store_inferior_registers; 00127 return t; 00128 } 00129 00130 00131 /* Support for debug registers. */ 00132 00133 #ifdef HAVE_PT_GETDBREGS 00134 00135 static unsigned long 00136 amd64bsd_dr_get (ptid_t ptid, int regnum) 00137 { 00138 struct dbreg dbregs; 00139 00140 if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), 00141 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) 00142 perror_with_name (_("Couldn't read debug registers")); 00143 00144 return DBREG_DRX ((&dbregs), regnum); 00145 } 00146 00147 static void 00148 amd64bsd_dr_set (int regnum, unsigned long value) 00149 { 00150 struct dbreg dbregs; 00151 00152 if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), 00153 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) 00154 perror_with_name (_("Couldn't get debug registers")); 00155 00156 /* For some mysterious reason, some of the reserved bits in the 00157 debug control register get set. Mask these off, otherwise the 00158 ptrace call below will fail. */ 00159 DBREG_DRX ((&dbregs), 7) &= ~(0xffffffff0000fc00); 00160 00161 DBREG_DRX ((&dbregs), regnum) = value; 00162 00163 if (ptrace (PT_SETDBREGS, ptid_get_pid (inferior_ptid), 00164 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) 00165 perror_with_name (_("Couldn't write debug registers")); 00166 } 00167 00168 void 00169 amd64bsd_dr_set_control (unsigned long control) 00170 { 00171 amd64bsd_dr_set (7, control); 00172 } 00173 00174 void 00175 amd64bsd_dr_set_addr (int regnum, CORE_ADDR addr) 00176 { 00177 gdb_assert (regnum >= 0 && regnum <= 4); 00178 00179 amd64bsd_dr_set (regnum, addr); 00180 } 00181 00182 CORE_ADDR 00183 amd64bsd_dr_get_addr (int regnum) 00184 { 00185 return amd64bsd_dr_get (inferior_ptid, regnum); 00186 } 00187 00188 unsigned long 00189 amd64bsd_dr_get_status (void) 00190 { 00191 return amd64bsd_dr_get (inferior_ptid, 6); 00192 } 00193 00194 unsigned long 00195 amd64bsd_dr_get_control (void) 00196 { 00197 return amd64bsd_dr_get (inferior_ptid, 7); 00198 } 00199 00200 #endif /* PT_GETDBREGS */