xref: /dflybsd-src/contrib/gdb-7/gdb/i386dfly-nat.c (revision 8a286ab35ddbd8fd8ac6b75a2820e262cf43e21c)
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