]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/gnu/usr.bin/binutils/gdbserver/low-fbsd.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / 6 / gnu / usr.bin / binutils / gdbserver / low-fbsd.c
1 /* Low level interface to ptrace, for the remote server for GDB.
2    Copyright (C) 1995 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 /* $FreeBSD$ */
21
22 #include "defs.h"
23 #include <sys/wait.h>
24 #include "frame.h"
25 #include "inferior.h"
26
27 #include <stdio.h>
28 #include <sys/param.h>
29 #include <dirent.h>
30 #include <sys/user.h>
31 #include <signal.h>
32 #include <sys/ioctl.h>
33 #include <sgtty.h>
34 #include <fcntl.h>
35 #include <string.h>
36
37 /***************Begin MY defs*********************/
38 int quit_flag = 0;
39 char registers[REGISTER_BYTES];
40
41 /* Index within `registers' of the first byte of the space for
42    register N.  */
43
44
45 char buf2[MAX_REGISTER_RAW_SIZE];
46 /***************End MY defs*********************/
47
48 #include <sys/ptrace.h>
49 #include <machine/reg.h>
50
51 extern char **environ;
52 extern int inferior_pid;
53 void quit (), perror_with_name ();
54 int query ();
55
56 /* Start an inferior process and returns its pid.
57    ALLARGS is a vector of program-name and args.
58    ENV is the environment vector to pass.  */
59
60 int
61 create_inferior (program, allargs)
62      char *program;
63      char **allargs;
64 {
65   int pid;
66
67   pid = fork ();
68   if (pid < 0)
69     perror_with_name ("fork");
70
71   if (pid == 0)
72     {
73       ptrace (PT_TRACE_ME, 0, 0, 0);
74
75       execv (program, allargs);
76
77       fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror(errno));
78       fflush (stderr);
79       _exit (0177);
80     }
81
82   return pid;
83 }
84
85 /* Kill the inferior process.  Make us have no inferior.  */
86
87 void
88 kill_inferior ()
89 {
90   if (inferior_pid == 0)
91     return;
92   ptrace (PT_KILL, inferior_pid, 0, 0);
93   wait (0);
94   /*************inferior_died ();****VK**************/
95 }
96
97 /* Return nonzero if the given thread is still alive.  */
98 int
99 mythread_alive (pid)
100      int pid;
101 {
102   return 1;
103 }
104
105 /* Wait for process, returns status */
106
107 unsigned char
108 mywait (status)
109      char *status;
110 {
111   int pid;
112   int w;
113
114   pid = wait (&w);
115   if (pid != inferior_pid)
116     perror_with_name ("wait");
117
118   if (WIFEXITED (w))
119     {
120       fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
121       *status = 'W';
122       return ((unsigned char) WEXITSTATUS (w));
123     }
124   else if (!WIFSTOPPED (w))
125     {
126       fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
127       *status = 'X';
128       return ((unsigned char) WTERMSIG (w));
129     }
130
131   fetch_inferior_registers (0);
132
133   *status = 'T';
134   return ((unsigned char) WSTOPSIG (w));
135 }
136
137 /* Resume execution of the inferior process.
138    If STEP is nonzero, single-step it.
139    If SIGNAL is nonzero, give it that signal.  */
140
141 void
142 myresume (step, signal)
143      int step;
144      int signal;
145 {
146   errno = 0;
147   ptrace (step ? PT_STEP : PT_CONTINUE, inferior_pid,
148           (PTRACE_ARG3_TYPE) 1, signal);
149   if (errno)
150     perror_with_name ("ptrace");
151 }
152
153 #if defined(__i386__)
154
155 /* this table must line up with REGISTER_NAMES in tm-i386v.h */
156 /* symbols like 'tEAX' come from <machine/reg.h> */
157 static int tregmap[] =
158 {
159   tEAX, tECX, tEDX, tEBX,
160   tESP, tEBP, tESI, tEDI,
161   tEIP, tEFLAGS, tCS, tSS,
162   tDS, tES, tFS, tGS,
163 };
164
165 static struct save87 pcb_savefpu;
166
167 void
168 fetch_inferior_registers (regno)
169      int regno;
170 {
171   struct reg inferior_registers;        /* ptrace order, not gcc/gdb order */
172   int r;
173
174   ptrace (PT_GETREGS, inferior_pid,
175           (PTRACE_ARG3_TYPE) &inferior_registers, 0);
176
177   for (r = 0; r < NUM_REGS; r++)
178     memcpy (&registers[REGISTER_BYTE (r)], ((int *)&inferior_registers) + tregmap[r], 4);
179 }
180
181 void
182 store_inferior_registers (regno)
183      int regno;
184 {
185   struct reg inferior_registers;        /* ptrace order, not gcc/gdb order */
186   int r;
187
188   ptrace (PT_GETREGS, inferior_pid,
189           (PTRACE_ARG3_TYPE) &inferior_registers, 0);
190
191   for (r = 0; r < NUM_REGS; r++)
192     memcpy (((int *)&inferior_registers) + tregmap[r], &registers[REGISTER_BYTE (r)], 4);
193
194   ptrace (PT_SETREGS, inferior_pid,
195           (PTRACE_ARG3_TYPE) &inferior_registers, 0);
196 }
197
198 #elif defined(__alpha__)
199
200 void
201 fetch_inferior_registers (regno)
202      int regno;
203 {
204   struct reg regs;      /* ptrace order, not gcc/gdb order */
205   struct fpreg fpregs;
206   int r;
207
208   ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
209   ptrace (PT_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
210
211   for (r = 0; r < 31; r++)
212     memcpy (&registers[REGISTER_BYTE (r)],
213             &regs.r_regs[r], sizeof(u_int64_t));
214   for (r = 0; r < 32; r++)
215     memcpy (&registers[REGISTER_BYTE (r + FP0_REGNUM)],
216             &fpregs.fpr_regs[r], sizeof(u_int64_t));
217   memcpy (&registers[REGISTER_BYTE (PC_REGNUM)],
218           &regs.r_regs[31], sizeof(u_int64_t));
219
220   memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, sizeof(u_int64_t));
221   memset (&registers[REGISTER_BYTE (FP_REGNUM)], 0, sizeof(u_int64_t));
222 }
223
224 void
225 store_inferior_registers (regno)
226      int regno;
227 {
228   struct reg regs;      /* ptrace order, not gcc/gdb order */
229   struct fpreg fpregs;
230   int r;
231
232   for (r = 0; r < 31; r++)
233     memcpy (&regs.r_regs[r],
234             &registers[REGISTER_BYTE (r)], sizeof(u_int64_t));
235   for (r = 0; r < 32; r++)
236     memcpy (&fpregs.fpr_regs[r],
237             &registers[REGISTER_BYTE (r + FP0_REGNUM)], sizeof(u_int64_t));
238   memcpy (&regs.r_regs[31],
239           &registers[REGISTER_BYTE (PC_REGNUM)], sizeof(u_int64_t));
240
241   ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
242   ptrace (PT_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
243 }
244
245 #endif
246
247
248 /* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
249    in the NEW_SUN_PTRACE case.
250    It ought to be straightforward.  But it appears that writing did
251    not write the data that I specified.  I cannot understand where
252    it got the data that it actually did write.  */
253
254 /* Copy LEN bytes from inferior's memory starting at MEMADDR
255    to debugger memory starting at MYADDR.  */
256
257 read_inferior_memory (memaddr, myaddr, len)
258      CORE_ADDR memaddr;
259      char *myaddr;
260      int len;
261 {
262   register int i;
263   /* Round starting address down to longword boundary.  */
264   register CORE_ADDR addr = memaddr & -sizeof (int);
265   /* Round ending address up; get number of longwords that makes.  */
266   register int count
267   = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
268   /* Allocate buffer of that many longwords.  */
269   register int *buffer = (int *) alloca (count * sizeof (int));
270
271   /* Read all the longwords */
272   for (i = 0; i < count; i++, addr += sizeof (int))
273     {
274       buffer[i] = ptrace (PT_READ_I, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
275     }
276
277   /* Copy appropriate bytes out of the buffer.  */
278   memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
279 }
280
281 /* Copy LEN bytes of data from debugger memory at MYADDR
282    to inferior's memory at MEMADDR.
283    On failure (cannot write the inferior)
284    returns the value of errno.  */
285
286 int
287 write_inferior_memory (memaddr, myaddr, len)
288      CORE_ADDR memaddr;
289      char *myaddr;
290      int len;
291 {
292   register int i;
293   /* Round starting address down to longword boundary.  */
294   register CORE_ADDR addr = memaddr & -sizeof (int);
295   /* Round ending address up; get number of longwords that makes.  */
296   register int count
297   = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
298   /* Allocate buffer of that many longwords.  */
299   register int *buffer = (int *) alloca (count * sizeof (int));
300   extern int errno;
301
302   /* Fill start and end extra bytes of buffer with existing memory data.  */
303
304   buffer[0] = ptrace (PT_READ_I, inferior_pid,
305                       (PTRACE_ARG3_TYPE) addr, 0);
306
307   if (count > 1)
308     {
309       buffer[count - 1]
310         = ptrace (PT_READ_I, inferior_pid,
311                   (PTRACE_ARG3_TYPE) addr + (count - 1) * sizeof (int), 0);
312     }
313
314   /* Copy data to be written over corresponding part of buffer */
315
316   memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
317
318   /* Write the entire buffer.  */
319
320   for (i = 0; i < count; i++, addr += sizeof (int))
321     {
322       errno = 0;
323       ptrace (PT_WRITE_I, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
324       if (errno)
325         return errno;
326     }
327
328   return 0;
329 }
330 \f
331 void
332 initialize ()
333 {
334   inferior_pid = 0;
335 }
336
337 int
338 have_inferior_p ()
339 {
340   return inferior_pid != 0;
341 }