169e0f06dSSimon Schubert /* Native-dependent code for DragonFly/i386. 269e0f06dSSimon Schubert 3*8a286ab3SJohn Marino Copyright (C) 2001-2013 Free Software Foundation, Inc. 469e0f06dSSimon Schubert 569e0f06dSSimon Schubert This file is part of GDB. 669e0f06dSSimon Schubert 769e0f06dSSimon Schubert This program is free software; you can redistribute it and/or modify 869e0f06dSSimon Schubert it under the terms of the GNU General Public License as published by 969e0f06dSSimon Schubert the Free Software Foundation; either version 3 of the License, or 1069e0f06dSSimon Schubert (at your option) any later version. 1169e0f06dSSimon Schubert 1269e0f06dSSimon Schubert This program is distributed in the hope that it will be useful, 1369e0f06dSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of 1469e0f06dSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1569e0f06dSSimon Schubert GNU General Public License for more details. 1669e0f06dSSimon Schubert 1769e0f06dSSimon Schubert You should have received a copy of the GNU General Public License 1869e0f06dSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1969e0f06dSSimon Schubert 2069e0f06dSSimon Schubert #include "defs.h" 2169e0f06dSSimon Schubert #include "inferior.h" 2269e0f06dSSimon Schubert #include "regcache.h" 2369e0f06dSSimon Schubert #include "target.h" 24*8a286ab3SJohn Marino #include "gregset.h" 2569e0f06dSSimon Schubert 2669e0f06dSSimon Schubert #include <sys/types.h> 27*8a286ab3SJohn Marino #include <sys/procfs.h> 2869e0f06dSSimon Schubert #include <sys/ptrace.h> 2969e0f06dSSimon Schubert #include <sys/sysctl.h> 3069e0f06dSSimon Schubert 3169e0f06dSSimon Schubert #include "fbsd-nat.h" 3269e0f06dSSimon Schubert #include "i386-tdep.h" 3369e0f06dSSimon Schubert #include "i386-nat.h" 3469e0f06dSSimon Schubert #include "i386bsd-nat.h" 3569e0f06dSSimon Schubert 36*8a286ab3SJohn Marino #ifdef DFLY_PCB_SUPPLY 37*8a286ab3SJohn Marino /* Resume execution of the inferior process. If STEP is nonzero, 38*8a286ab3SJohn Marino single-step it. If SIGNAL is nonzero, give it that signal. */ 39*8a286ab3SJohn Marino 40*8a286ab3SJohn Marino static void 41*8a286ab3SJohn Marino i386dfly_resume (struct target_ops *ops, 42*8a286ab3SJohn Marino ptid_t ptid, int step, enum gdb_signal signal) 43*8a286ab3SJohn Marino { 44*8a286ab3SJohn Marino pid_t pid = ptid_get_pid (ptid); 45*8a286ab3SJohn Marino int request = PT_STEP; 46*8a286ab3SJohn Marino 47*8a286ab3SJohn Marino if (pid == -1) 48*8a286ab3SJohn Marino /* Resume all threads. This only gets used in the non-threaded 49*8a286ab3SJohn Marino case, where "resume all threads" and "resume inferior_ptid" are 50*8a286ab3SJohn Marino the same. */ 51*8a286ab3SJohn Marino pid = ptid_get_pid (inferior_ptid); 52*8a286ab3SJohn Marino 53*8a286ab3SJohn Marino if (!step) 54*8a286ab3SJohn Marino { 55*8a286ab3SJohn Marino struct regcache *regcache = get_current_regcache (); 56*8a286ab3SJohn Marino ULONGEST eflags; 57*8a286ab3SJohn Marino 58*8a286ab3SJohn Marino /* Workaround for a bug in FreeBSD. Make sure that the trace 59*8a286ab3SJohn Marino flag is off when doing a continue. There is a code path 60*8a286ab3SJohn Marino through the kernel which leaves the flag set when it should 61*8a286ab3SJohn Marino have been cleared. If a process has a signal pending (such 62*8a286ab3SJohn Marino as SIGALRM) and we do a PT_STEP, the process never really has 63*8a286ab3SJohn Marino a chance to run because the kernel needs to notify the 64*8a286ab3SJohn Marino debugger that a signal is being sent. Therefore, the process 65*8a286ab3SJohn Marino never goes through the kernel's trap() function which would 66*8a286ab3SJohn Marino normally clear it. */ 67*8a286ab3SJohn Marino 68*8a286ab3SJohn Marino regcache_cooked_read_unsigned (regcache, I386_EFLAGS_REGNUM, 69*8a286ab3SJohn Marino &eflags); 70*8a286ab3SJohn Marino if (eflags & 0x0100) 71*8a286ab3SJohn Marino regcache_cooked_write_unsigned (regcache, I386_EFLAGS_REGNUM, 72*8a286ab3SJohn Marino eflags & ~0x0100); 73*8a286ab3SJohn Marino 74*8a286ab3SJohn Marino request = PT_CONTINUE; 75*8a286ab3SJohn Marino } 76*8a286ab3SJohn Marino 77*8a286ab3SJohn Marino /* An addres of (caddr_t) 1 tells ptrace to continue from where it 78*8a286ab3SJohn Marino was. (If GDB wanted it to start some other way, we have already 79*8a286ab3SJohn Marino written a new PC value to the child.) */ 80*8a286ab3SJohn Marino if (ptrace (request, pid, (caddr_t) 1, 81*8a286ab3SJohn Marino gdb_signal_to_host (signal)) == -1) 82*8a286ab3SJohn Marino perror_with_name (("ptrace")); 83*8a286ab3SJohn Marino } 84*8a286ab3SJohn Marino 85*8a286ab3SJohn Marino 86*8a286ab3SJohn Marino /* Transfering the registers between GDB, inferiors and core files. */ 87*8a286ab3SJohn Marino 88*8a286ab3SJohn Marino /* Fill GDB's register array with the general-purpose register values 89*8a286ab3SJohn Marino in *GREGSETP. */ 90*8a286ab3SJohn Marino 91*8a286ab3SJohn Marino void 92*8a286ab3SJohn Marino supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) 93*8a286ab3SJohn Marino { 94*8a286ab3SJohn Marino i386bsd_supply_gregset (regcache, gregsetp); 95*8a286ab3SJohn Marino } 96*8a286ab3SJohn Marino 97*8a286ab3SJohn Marino /* Fill register REGNUM (if it is a general-purpose register) in 98*8a286ab3SJohn Marino *GREGSETPS with the value in GDB's register array. If REGNUM is -1, 99*8a286ab3SJohn Marino do this for all registers. */ 100*8a286ab3SJohn Marino 101*8a286ab3SJohn Marino void 102*8a286ab3SJohn Marino fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregsetp, int regnum) 103*8a286ab3SJohn Marino { 104*8a286ab3SJohn Marino i386bsd_collect_gregset (regcache, gregsetp, regnum); 105*8a286ab3SJohn Marino } 106*8a286ab3SJohn Marino 107*8a286ab3SJohn Marino #include "i387-tdep.h" 108*8a286ab3SJohn Marino 109*8a286ab3SJohn Marino /* Fill GDB's register array with the floating-point register values 110*8a286ab3SJohn Marino in *FPREGSETP. */ 111*8a286ab3SJohn Marino 112*8a286ab3SJohn Marino void 113*8a286ab3SJohn Marino supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) 114*8a286ab3SJohn Marino { 115*8a286ab3SJohn Marino i387_supply_fsave (regcache, -1, fpregsetp); 116*8a286ab3SJohn Marino } 117*8a286ab3SJohn Marino 118*8a286ab3SJohn Marino /* Fill register REGNUM (if it is a floating-point register) in 119*8a286ab3SJohn Marino *FPREGSETP with the value in GDB's register array. If REGNUM is -1, 120*8a286ab3SJohn Marino do this for all registers. */ 121*8a286ab3SJohn Marino 122*8a286ab3SJohn Marino void 123*8a286ab3SJohn Marino fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regnum) 124*8a286ab3SJohn Marino { 125*8a286ab3SJohn Marino i387_collect_fsave (regcache, regnum, fpregsetp); 126*8a286ab3SJohn Marino } 127*8a286ab3SJohn Marino 128*8a286ab3SJohn Marino 129*8a286ab3SJohn Marino /* Support for debugging kernel virtual memory images. */ 130*8a286ab3SJohn Marino 131*8a286ab3SJohn Marino #include <sys/types.h> 132*8a286ab3SJohn Marino #include <machine/pcb.h> 133*8a286ab3SJohn Marino 134*8a286ab3SJohn Marino #include "bsd-kvm.h" 135*8a286ab3SJohn Marino 136*8a286ab3SJohn Marino static int 137*8a286ab3SJohn Marino i386dfly_supply_pcb (struct regcache *regcache, struct pcb *pcb) 138*8a286ab3SJohn Marino { 139*8a286ab3SJohn Marino /* The following is true for FreeBSD 4.7: 140*8a286ab3SJohn Marino 141*8a286ab3SJohn Marino The pcb contains %eip, %ebx, %esp, %ebp, %esi, %edi and %gs. 142*8a286ab3SJohn Marino This accounts for all callee-saved registers specified by the 143*8a286ab3SJohn Marino psABI and then some. Here %esp contains the stack pointer at the 144*8a286ab3SJohn Marino point just after the call to cpu_switch(). From this information 145*8a286ab3SJohn Marino we reconstruct the register state as it would look when we just 146*8a286ab3SJohn Marino returned from cpu_switch(). */ 147*8a286ab3SJohn Marino 148*8a286ab3SJohn Marino /* The stack pointer shouldn't be zero. */ 149*8a286ab3SJohn Marino if (pcb->pcb_esp == 0) 150*8a286ab3SJohn Marino return 0; 151*8a286ab3SJohn Marino 152*8a286ab3SJohn Marino pcb->pcb_esp += 4; 153*8a286ab3SJohn Marino regcache_raw_supply (regcache, I386_EDI_REGNUM, &pcb->pcb_edi); 154*8a286ab3SJohn Marino regcache_raw_supply (regcache, I386_ESI_REGNUM, &pcb->pcb_esi); 155*8a286ab3SJohn Marino regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); 156*8a286ab3SJohn Marino regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); 157*8a286ab3SJohn Marino regcache_raw_supply (regcache, I386_EBX_REGNUM, &pcb->pcb_ebx); 158*8a286ab3SJohn Marino regcache_raw_supply (regcache, I386_EIP_REGNUM, &pcb->pcb_eip); 159*8a286ab3SJohn Marino regcache_raw_supply (regcache, I386_GS_REGNUM, &pcb->pcb_gs); 160*8a286ab3SJohn Marino 161*8a286ab3SJohn Marino return 1; 162*8a286ab3SJohn Marino } 163*8a286ab3SJohn Marino #endif /* DFLY_PCB_SUPPLY */ 164*8a286ab3SJohn Marino 165*8a286ab3SJohn Marino 16669e0f06dSSimon Schubert /* Prevent warning from -Wmissing-prototypes. */ 16769e0f06dSSimon Schubert void _initialize_i386dfly_nat (void); 16869e0f06dSSimon Schubert 16969e0f06dSSimon Schubert void 17069e0f06dSSimon Schubert _initialize_i386dfly_nat (void) 17169e0f06dSSimon Schubert { 17269e0f06dSSimon Schubert struct target_ops *t; 17369e0f06dSSimon Schubert 17469e0f06dSSimon Schubert /* Add some extra features to the common *BSD/i386 target. */ 17569e0f06dSSimon Schubert t = i386bsd_target (); 17669e0f06dSSimon Schubert 17769e0f06dSSimon Schubert #ifdef HAVE_PT_GETDBREGS 17869e0f06dSSimon Schubert 17969e0f06dSSimon Schubert i386_use_watchpoints (t); 18069e0f06dSSimon Schubert 18169e0f06dSSimon Schubert i386_dr_low.set_control = i386bsd_dr_set_control; 18269e0f06dSSimon Schubert i386_dr_low.set_addr = i386bsd_dr_set_addr; 183*8a286ab3SJohn Marino i386_dr_low.get_addr = i386bsd_dr_get_addr; 18469e0f06dSSimon Schubert i386_dr_low.get_status = i386bsd_dr_get_status; 185*8a286ab3SJohn Marino i386_dr_low.get_control = i386bsd_dr_get_control; 18669e0f06dSSimon Schubert i386_set_debug_register_length (4); 18769e0f06dSSimon Schubert 18869e0f06dSSimon Schubert #endif /* HAVE_PT_GETDBREGS */ 18969e0f06dSSimon Schubert 19069e0f06dSSimon Schubert 19169e0f06dSSimon Schubert t->to_pid_to_exec_file = fbsd_pid_to_exec_file; 19269e0f06dSSimon Schubert t->to_find_memory_regions = fbsd_find_memory_regions; 19369e0f06dSSimon Schubert t->to_make_corefile_notes = fbsd_make_corefile_notes; 19469e0f06dSSimon Schubert add_target (t); 19569e0f06dSSimon Schubert 196*8a286ab3SJohn Marino #ifdef DFLY_PCB_SUPPLY 197*8a286ab3SJohn Marino /* Support debugging kernel virtual memory images. */ 198*8a286ab3SJohn Marino bsd_kvm_add_target (i386dfly_supply_pcb); 199*8a286ab3SJohn Marino #endif 200*8a286ab3SJohn Marino 20169e0f06dSSimon Schubert /* DragonFly provides a kern.ps_strings sysctl that we can use to 20269e0f06dSSimon Schubert locate the sigtramp. That way we can still recognize a sigtramp 20369e0f06dSSimon Schubert if its location is changed in a new kernel. Of course this is 20469e0f06dSSimon Schubert still based on the assumption that the sigtramp is placed 20569e0f06dSSimon Schubert directly under the location where the program arguments and 20669e0f06dSSimon Schubert environment can be found. */ 20769e0f06dSSimon Schubert #ifdef KERN_PS_STRINGS 20869e0f06dSSimon Schubert { 20969e0f06dSSimon Schubert int mib[2]; 21069e0f06dSSimon Schubert u_long ps_strings; 21169e0f06dSSimon Schubert size_t len; 21269e0f06dSSimon Schubert 21369e0f06dSSimon Schubert mib[0] = CTL_KERN; 21469e0f06dSSimon Schubert mib[1] = KERN_PS_STRINGS; 21569e0f06dSSimon Schubert len = sizeof (ps_strings); 21669e0f06dSSimon Schubert if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0) 21769e0f06dSSimon Schubert { 21869e0f06dSSimon Schubert i386dfly_sigtramp_start_addr = ps_strings - 128; 21969e0f06dSSimon Schubert i386dfly_sigtramp_end_addr = ps_strings; 22069e0f06dSSimon Schubert } 22169e0f06dSSimon Schubert } 22269e0f06dSSimon Schubert #endif 22369e0f06dSSimon Schubert } 224