gdb - Fix indentantion in DragonFly specific files.
[dragonfly.git] / contrib / gdb-7 / gdb / i386dfly-nat.c
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 }