xref: /dflybsd-src/contrib/gdb-7/gdb/i386dfly-nat.c (revision e0cb4e00e7683d8be35887ea90c8e33e065e45c0)
169e0f06dSSimon Schubert /* Native-dependent code for DragonFly/i386.
269e0f06dSSimon Schubert 
38a286ab3SJohn 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"
248a286ab3SJohn Marino #include "gregset.h"
2569e0f06dSSimon Schubert 
2669e0f06dSSimon Schubert #include <sys/types.h>
278a286ab3SJohn 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 
368a286ab3SJohn Marino #ifdef DFLY_PCB_SUPPLY
378a286ab3SJohn Marino /* Resume execution of the inferior process.  If STEP is nonzero,
388a286ab3SJohn Marino    single-step it.  If SIGNAL is nonzero, give it that signal.  */
398a286ab3SJohn Marino 
408a286ab3SJohn Marino static void
i386dfly_resume(struct target_ops * ops,ptid_t ptid,int step,enum gdb_signal signal)418a286ab3SJohn Marino i386dfly_resume (struct target_ops *ops,
428a286ab3SJohn Marino 		 ptid_t ptid, int step, enum gdb_signal signal)
438a286ab3SJohn Marino {
448a286ab3SJohn Marino   pid_t pid = ptid_get_pid (ptid);
458a286ab3SJohn Marino   int request = PT_STEP;
468a286ab3SJohn Marino 
478a286ab3SJohn Marino   if (pid == -1)
48*e0cb4e00SSascha Wildner     /* Resume all threads.  This only gets used in the non-threaded
49*e0cb4e00SSascha Wildner        case, where "resume all threads" and "resume inferior_ptid" are
50*e0cb4e00SSascha Wildner        the same.  */
518a286ab3SJohn Marino     pid = ptid_get_pid (inferior_ptid);
528a286ab3SJohn Marino 
53*e0cb4e00SSascha Wildner   if (!step)
54*e0cb4e00SSascha Wildner     {
558a286ab3SJohn Marino       struct regcache *regcache = get_current_regcache ();
568a286ab3SJohn Marino       ULONGEST eflags;
578a286ab3SJohn Marino 
588a286ab3SJohn Marino       /* Workaround for a bug in FreeBSD.  Make sure that the trace
59*e0cb4e00SSascha Wildner  	 flag is off when doing a continue.  There is a code path
60*e0cb4e00SSascha Wildner  	 through the kernel which leaves the flag set when it should
61*e0cb4e00SSascha Wildner  	 have been cleared.  If a process has a signal pending (such
62*e0cb4e00SSascha Wildner  	 as SIGALRM) and we do a PT_STEP, the process never really has
63*e0cb4e00SSascha Wildner  	 a chance to run because the kernel needs to notify the
64*e0cb4e00SSascha Wildner  	 debugger that a signal is being sent.  Therefore, the process
65*e0cb4e00SSascha Wildner  	 never goes through the kernel's trap() function which would
66*e0cb4e00SSascha Wildner  	 normally clear it.  */
678a286ab3SJohn Marino 
688a286ab3SJohn Marino       regcache_cooked_read_unsigned (regcache, I386_EFLAGS_REGNUM,
698a286ab3SJohn Marino 				     &eflags);
708a286ab3SJohn Marino       if (eflags & 0x0100)
718a286ab3SJohn Marino 	regcache_cooked_write_unsigned (regcache, I386_EFLAGS_REGNUM,
728a286ab3SJohn Marino 					eflags & ~0x0100);
738a286ab3SJohn Marino 
748a286ab3SJohn Marino       request = PT_CONTINUE;
758a286ab3SJohn Marino     }
76*e0cb4e00SSascha Wildner 
778a286ab3SJohn Marino   /* An addres of (caddr_t) 1 tells ptrace to continue from where it
78*e0cb4e00SSascha Wildner      was.  (If GDB wanted it to start some other way, we have already
79*e0cb4e00SSascha Wildner      written a new PC value to the child.)  */
808a286ab3SJohn Marino   if (ptrace (request, pid, (caddr_t) 1,
818a286ab3SJohn Marino 	      gdb_signal_to_host (signal)) == -1)
828a286ab3SJohn Marino     perror_with_name (("ptrace"));
838a286ab3SJohn Marino }
84*e0cb4e00SSascha Wildner 
858a286ab3SJohn Marino 
868a286ab3SJohn Marino /* Transfering the registers between GDB, inferiors and core files.  */
878a286ab3SJohn Marino 
888a286ab3SJohn Marino /* Fill GDB's register array with the general-purpose register values
898a286ab3SJohn Marino    in *GREGSETP.  */
908a286ab3SJohn Marino 
918a286ab3SJohn Marino void
supply_gregset(struct regcache * regcache,const gregset_t * gregsetp)928a286ab3SJohn Marino supply_gregset (struct regcache *regcache, const gregset_t *gregsetp)
938a286ab3SJohn Marino {
948a286ab3SJohn Marino   i386bsd_supply_gregset (regcache, gregsetp);
958a286ab3SJohn Marino }
968a286ab3SJohn Marino 
978a286ab3SJohn Marino /* Fill register REGNUM (if it is a general-purpose register) in
988a286ab3SJohn Marino    *GREGSETPS with the value in GDB's register array.  If REGNUM is -1,
998a286ab3SJohn Marino    do this for all registers.  */
1008a286ab3SJohn Marino 
1018a286ab3SJohn Marino void
fill_gregset(const struct regcache * regcache,gdb_gregset_t * gregsetp,int regnum)1028a286ab3SJohn Marino fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregsetp, int regnum)
1038a286ab3SJohn Marino {
1048a286ab3SJohn Marino   i386bsd_collect_gregset (regcache, gregsetp, regnum);
1058a286ab3SJohn Marino }
1068a286ab3SJohn Marino 
1078a286ab3SJohn Marino #include "i387-tdep.h"
1088a286ab3SJohn Marino 
1098a286ab3SJohn Marino /* Fill GDB's register array with the floating-point register values
1108a286ab3SJohn Marino    in *FPREGSETP.  */
1118a286ab3SJohn Marino 
1128a286ab3SJohn Marino void
supply_fpregset(struct regcache * regcache,const fpregset_t * fpregsetp)1138a286ab3SJohn Marino supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp)
1148a286ab3SJohn Marino {
1158a286ab3SJohn Marino   i387_supply_fsave (regcache, -1, fpregsetp);
1168a286ab3SJohn Marino }
1178a286ab3SJohn Marino 
1188a286ab3SJohn Marino /* Fill register REGNUM (if it is a floating-point register) in
1198a286ab3SJohn Marino    *FPREGSETP with the value in GDB's register array.  If REGNUM is -1,
1208a286ab3SJohn Marino    do this for all registers.  */
1218a286ab3SJohn Marino 
1228a286ab3SJohn Marino void
fill_fpregset(const struct regcache * regcache,gdb_fpregset_t * fpregsetp,int regnum)1238a286ab3SJohn Marino fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regnum)
1248a286ab3SJohn Marino {
1258a286ab3SJohn Marino   i387_collect_fsave (regcache, regnum, fpregsetp);
1268a286ab3SJohn Marino }
127*e0cb4e00SSascha Wildner 
1288a286ab3SJohn Marino 
1298a286ab3SJohn Marino /* Support for debugging kernel virtual memory images.  */
1308a286ab3SJohn Marino 
1318a286ab3SJohn Marino #include <sys/types.h>
1328a286ab3SJohn Marino #include <machine/pcb.h>
1338a286ab3SJohn Marino 
1348a286ab3SJohn Marino #include "bsd-kvm.h"
1358a286ab3SJohn Marino 
1368a286ab3SJohn Marino static int
i386dfly_supply_pcb(struct regcache * regcache,struct pcb * pcb)1378a286ab3SJohn Marino i386dfly_supply_pcb (struct regcache *regcache, struct pcb *pcb)
1388a286ab3SJohn Marino {
1398a286ab3SJohn Marino   /* The following is true for FreeBSD 4.7:
140*e0cb4e00SSascha Wildner 
141*e0cb4e00SSascha Wildner      The pcb contains %eip, %ebx, %esp, %ebp, %esi, %edi and %gs.
142*e0cb4e00SSascha Wildner      This accounts for all callee-saved registers specified by the
143*e0cb4e00SSascha Wildner      psABI and then some.  Here %esp contains the stack pointer at the
144*e0cb4e00SSascha Wildner      point just after the call to cpu_switch().  From this information
145*e0cb4e00SSascha Wildner      we reconstruct the register state as it would look when we just
146*e0cb4e00SSascha Wildner      returned from cpu_switch().  */
1478a286ab3SJohn Marino 
1488a286ab3SJohn Marino   /* The stack pointer shouldn't be zero.  */
1498a286ab3SJohn Marino   if (pcb->pcb_esp == 0)
1508a286ab3SJohn Marino     return 0;
1518a286ab3SJohn Marino 
1528a286ab3SJohn Marino   pcb->pcb_esp += 4;
1538a286ab3SJohn Marino   regcache_raw_supply (regcache, I386_EDI_REGNUM, &pcb->pcb_edi);
1548a286ab3SJohn Marino   regcache_raw_supply (regcache, I386_ESI_REGNUM, &pcb->pcb_esi);
1558a286ab3SJohn Marino   regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp);
1568a286ab3SJohn Marino   regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp);
1578a286ab3SJohn Marino   regcache_raw_supply (regcache, I386_EBX_REGNUM, &pcb->pcb_ebx);
1588a286ab3SJohn Marino   regcache_raw_supply (regcache, I386_EIP_REGNUM, &pcb->pcb_eip);
1598a286ab3SJohn Marino   regcache_raw_supply (regcache, I386_GS_REGNUM, &pcb->pcb_gs);
1608a286ab3SJohn Marino 
1618a286ab3SJohn Marino   return 1;
1628a286ab3SJohn Marino }
1638a286ab3SJohn Marino #endif /* DFLY_PCB_SUPPLY */
164*e0cb4e00SSascha Wildner 
1658a286ab3SJohn Marino 
16669e0f06dSSimon Schubert /* Prevent warning from -Wmissing-prototypes.  */
16769e0f06dSSimon Schubert void _initialize_i386dfly_nat (void);
16869e0f06dSSimon Schubert 
16969e0f06dSSimon Schubert void
_initialize_i386dfly_nat(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;
1838a286ab3SJohn Marino   i386_dr_low.get_addr = i386bsd_dr_get_addr;
18469e0f06dSSimon Schubert   i386_dr_low.get_status = i386bsd_dr_get_status;
1858a286ab3SJohn 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 
1968a286ab3SJohn Marino #ifdef DFLY_PCB_SUPPLY
1978a286ab3SJohn Marino   /* Support debugging kernel virtual memory images.  */
1988a286ab3SJohn Marino   bsd_kvm_add_target (i386dfly_supply_pcb);
1998a286ab3SJohn Marino #endif
2008a286ab3SJohn Marino 
20169e0f06dSSimon Schubert   /* DragonFly provides a kern.ps_strings sysctl that we can use to
202*e0cb4e00SSascha Wildner      locate the sigtramp.  That way we can still recognize a sigtramp
203*e0cb4e00SSascha Wildner      if its location is changed in a new kernel.  Of course this is
204*e0cb4e00SSascha Wildner      still based on the assumption that the sigtramp is placed
205*e0cb4e00SSascha Wildner      directly under the location where the program arguments and
206*e0cb4e00SSascha Wildner      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);
216*e0cb4e00SSascha Wildner     if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
217*e0cb4e00SSascha Wildner       {
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