1 /* Native-dependent code for DragonFly/i386. 2 3 Copyright (C) 2001-2013 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 "regcache.h" 23 #include "target.h" 24 #include "gregset.h" 25 26 #include <sys/types.h> 27 #include <sys/procfs.h> 28 #include <sys/ptrace.h> 29 #include <sys/sysctl.h> 30 31 #include "fbsd-nat.h" 32 #include "i386-tdep.h" 33 #include "i386-nat.h" 34 #include "i386bsd-nat.h" 35 36 #ifdef DFLY_PCB_SUPPLY 37 /* Resume execution of the inferior process. If STEP is nonzero, 38 single-step it. If SIGNAL is nonzero, give it that signal. */ 39 40 static void 41 i386dfly_resume(struct target_ops *ops, 42 ptid_t ptid, int step, enum gdb_signal signal) 43 { 44 pid_t pid = ptid_get_pid(ptid); 45 int request = PT_STEP; 46 47 if (pid == -1) 48 /* Resume all threads. This only gets used in the 49 * non-threaded case, where "resume all threads" and "resume 50 * inferior_ptid" are the same. */ 51 pid = ptid_get_pid(inferior_ptid); 52 53 if (!step) { 54 struct regcache *regcache = get_current_regcache(); 55 ULONGEST eflags; 56 57 /* Workaround for a bug in FreeBSD. Make sure that the trace 58 * flag is off when doing a continue. There is a code path 59 * through the kernel which leaves the flag set when it should 60 * have been cleared. If a process has a signal pending (such 61 * as SIGALRM) and we do a PT_STEP, the process never really 62 * has a chance to run because the kernel needs to notify the 63 * debugger that a signal is being sent. Therefore, the 64 * process never goes through the kernel's trap() function 65 * which would normally clear it. */ 66 67 regcache_cooked_read_unsigned(regcache, I386_EFLAGS_REGNUM, 68 &eflags); 69 if (eflags & 0x0100) 70 regcache_cooked_write_unsigned(regcache, I386_EFLAGS_REGNUM, 71 eflags & ~0x0100); 72 73 request = PT_CONTINUE; 74 } 75 /* An addres of (caddr_t) 1 tells ptrace to continue from where it 76 * was. (If GDB wanted it to start some other way, we have already 77 * written a new PC value to the child.) */ 78 if (ptrace(request, pid, (caddr_t) 1, 79 gdb_signal_to_host(signal)) == -1) 80 perror_with_name(("ptrace")); 81 } 82 83 84 85 /* Transfering the registers between GDB, inferiors and core files. */ 86 87 /* Fill GDB's register array with the general-purpose register values 88 in *GREGSETP. */ 89 90 void 91 supply_gregset(struct regcache *regcache, const gregset_t * gregsetp) 92 { 93 i386bsd_supply_gregset(regcache, gregsetp); 94 } 95 96 /* Fill register REGNUM (if it is a general-purpose register) in 97 *GREGSETPS with the value in GDB's register array. If REGNUM is -1, 98 do this for all registers. */ 99 100 void 101 fill_gregset(const struct regcache *regcache, gdb_gregset_t * gregsetp, int regnum) 102 { 103 i386bsd_collect_gregset(regcache, gregsetp, regnum); 104 } 105 106 #include "i387-tdep.h" 107 108 /* Fill GDB's register array with the floating-point register values 109 in *FPREGSETP. */ 110 111 void 112 supply_fpregset(struct regcache *regcache, const fpregset_t * fpregsetp) 113 { 114 i387_supply_fsave(regcache, -1, fpregsetp); 115 } 116 117 /* Fill register REGNUM (if it is a floating-point register) in 118 *FPREGSETP with the value in GDB's register array. If REGNUM is -1, 119 do this for all registers. */ 120 121 void 122 fill_fpregset(const struct regcache *regcache, gdb_fpregset_t * fpregsetp, int regnum) 123 { 124 i387_collect_fsave(regcache, regnum, fpregsetp); 125 } 126 127 128 129 /* Support for debugging kernel virtual memory images. */ 130 131 #include <sys/types.h> 132 #include <machine/pcb.h> 133 134 #include "bsd-kvm.h" 135 136 static int 137 i386dfly_supply_pcb(struct regcache *regcache, struct pcb *pcb) 138 { 139 /* The following is true for FreeBSD 4.7: 140 * 141 * The pcb contains %eip, %ebx, %esp, %ebp, %esi, %edi and %gs. This 142 * accounts for all callee-saved registers specified by the psABI and 143 * then some. Here %esp contains the stack pointer at the point just 144 * after the call to cpu_switch(). From this information we 145 * reconstruct the register state as it would look when we just 146 * returned from cpu_switch(). */ 147 148 /* The stack pointer shouldn't be zero. */ 149 if (pcb->pcb_esp == 0) 150 return 0; 151 152 pcb->pcb_esp += 4; 153 regcache_raw_supply(regcache, I386_EDI_REGNUM, &pcb->pcb_edi); 154 regcache_raw_supply(regcache, I386_ESI_REGNUM, &pcb->pcb_esi); 155 regcache_raw_supply(regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); 156 regcache_raw_supply(regcache, I386_ESP_REGNUM, &pcb->pcb_esp); 157 regcache_raw_supply(regcache, I386_EBX_REGNUM, &pcb->pcb_ebx); 158 regcache_raw_supply(regcache, I386_EIP_REGNUM, &pcb->pcb_eip); 159 regcache_raw_supply(regcache, I386_GS_REGNUM, &pcb->pcb_gs); 160 161 return 1; 162 } 163 #endif /* DFLY_PCB_SUPPLY */ 164 165 166 167 /* Prevent warning from -Wmissing-prototypes. */ 168 void _initialize_i386dfly_nat(void); 169 170 void 171 _initialize_i386dfly_nat(void) 172 { 173 struct target_ops *t; 174 175 /* Add some extra features to the common *BSD/i386 target. */ 176 t = i386bsd_target(); 177 178 #ifdef HAVE_PT_GETDBREGS 179 180 i386_use_watchpoints(t); 181 182 i386_dr_low.set_control = i386bsd_dr_set_control; 183 i386_dr_low.set_addr = i386bsd_dr_set_addr; 184 i386_dr_low.get_addr = i386bsd_dr_get_addr; 185 i386_dr_low.get_status = i386bsd_dr_get_status; 186 i386_dr_low.get_control = i386bsd_dr_get_control; 187 i386_set_debug_register_length(4); 188 189 #endif /* HAVE_PT_GETDBREGS */ 190 191 192 t->to_pid_to_exec_file = fbsd_pid_to_exec_file; 193 t->to_find_memory_regions = fbsd_find_memory_regions; 194 t->to_make_corefile_notes = fbsd_make_corefile_notes; 195 add_target(t); 196 197 #ifdef DFLY_PCB_SUPPLY 198 /* Support debugging kernel virtual memory images. */ 199 bsd_kvm_add_target(i386dfly_supply_pcb); 200 #endif 201 202 /* DragonFly provides a kern.ps_strings sysctl that we can use to 203 * locate the sigtramp. That way we can still recognize a sigtramp if 204 * its location is changed in a new kernel. Of course this is still 205 * based on the assumption that the sigtramp is placed directly under 206 * the location where the program arguments and environment can be 207 * found. */ 208 #ifdef KERN_PS_STRINGS 209 { 210 int mib[2]; 211 u_long ps_strings; 212 size_t len; 213 214 mib[0] = CTL_KERN; 215 mib[1] = KERN_PS_STRINGS; 216 len = sizeof(ps_strings); 217 if (sysctl(mib, 2, &ps_strings, &len, NULL, 0) == 0) { 218 i386dfly_sigtramp_start_addr = ps_strings - 128; 219 i386dfly_sigtramp_end_addr = ps_strings; 220 } 221 } 222 #endif 223 } 224