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