]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/gdbserver/low-lynx.c
1 /* Low level interface to ptrace, for the remote server for GDB.
2 Copyright (C) 1986, 1987, 1993 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
25 #include <sys/param.h>
29 #include <sys/signal.h>
31 #include <sys/kernel.h>
32 #include <sys/itimer.h>
34 #include <sys/resource.h>
37 #include <sys/ioctl.h>
40 #include "/usr/include/wait.h"
42 char registers
[REGISTER_BYTES
];
44 #include <sys/ptrace.h>
46 /* Start an inferior process and returns its pid.
47 ALLARGS is a vector of program-name and args. */
50 create_inferior (program
, allargs
)
58 perror_with_name ("fork");
64 /* Switch child to it's own process group so that signals won't
65 directly affect gdbserver. */
69 ioctl (0, TIOCSPGRP
, &pgrp
);
71 ptrace (PTRACE_TRACEME
);
73 execv (program
, allargs
);
75 fprintf (stderr
, "GDBserver (process %d): Cannot exec %s: %s.\n",
77 errno
< sys_nerr
? sys_errlist
[errno
] : "unknown error");
85 /* Kill the inferior process. Make us have no inferior. */
90 if (inferior_pid
== 0)
92 ptrace (PTRACE_KILL
, inferior_pid
, 0, 0);
98 /* Wait for process, returns status */
113 if (pid
!= PIDGET(inferior_pid
))
114 perror_with_name ("wait");
116 inferior_pid
= BUILDPID (inferior_pid
, w
.w_tid
);
120 fprintf (stderr
, "\nChild exited with status %d\n", WEXITSTATUS (w
));
121 fprintf (stderr
, "GDBserver exiting\n");
124 else if (!WIFSTOPPED (w
))
126 fprintf (stderr
, "\nChild terminated with signal = %x \n", WTERMSIG (w
));
128 return ((unsigned char) WTERMSIG (w
));
131 fetch_inferior_registers (0);
134 return ((unsigned char) WSTOPSIG (w
));
137 /* Resume execution of the inferior process.
138 If STEP is nonzero, single-step it.
139 If SIGNAL is nonzero, give it that signal. */
142 myresume (step
, signal
)
147 ptrace (step
? PTRACE_SINGLESTEP
: PTRACE_CONT
, inferior_pid
, 1, signal
);
149 perror_with_name ("ptrace");
153 #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
155 /* Mapping between GDB register #s and offsets into econtext. Must be
156 consistent with REGISTER_NAMES macro in various tmXXX.h files. */
158 #define X(ENTRY)(offsetof(struct econtext, ENTRY))
161 /* Mappings from tm-i386v.h */
163 static int regmap
[] =
179 X(ecode
), /* Lynx doesn't give us either fs or gs, so */
180 X(fault
), /* we just substitute these two in the hopes
181 that they are useful. */
186 /* Mappings from tm-m68k.h */
188 static int regmap
[] =
200 X(regs
[10]), /* a2 */
201 X(regs
[11]), /* a3 */
202 X(regs
[12]), /* a4 */
203 X(regs
[13]), /* a5 */
204 X(regs
[14]), /* fp */
209 X(fregs
[0*3]), /* fp0 */
210 X(fregs
[1*3]), /* fp1 */
211 X(fregs
[2*3]), /* fp2 */
212 X(fregs
[3*3]), /* fp3 */
213 X(fregs
[4*3]), /* fp4 */
214 X(fregs
[5*3]), /* fp5 */
215 X(fregs
[6*3]), /* fp6 */
216 X(fregs
[7*3]), /* fp7 */
218 X(fcregs
[0]), /* fpcontrol */
219 X(fcregs
[1]), /* fpstatus */
220 X(fcregs
[2]), /* fpiaddr */
222 X(fault
), /* fpflags */
226 /* Return the offset relative to the start of the per-thread data to the
227 saved context block. */
230 lynx_registers_addr()
233 int ecpoff
= offsetof(st_t
, ecp
);
237 stblock
= (CORE_ADDR
) ptrace (PTRACE_THREADUSER
, inferior_pid
,
238 (PTRACE_ARG3_TYPE
)0, 0);
240 perror_with_name ("PTRACE_THREADUSER");
242 ecp
= (CORE_ADDR
) ptrace (PTRACE_PEEKTHREAD
, inferior_pid
,
243 (PTRACE_ARG3_TYPE
)ecpoff
, 0);
245 perror_with_name ("lynx_registers_addr(PTRACE_PEEKTHREAD)");
247 return ecp
- stblock
;
250 /* Fetch one or more registers from the inferior. REGNO == -1 to get
251 them all. We actually fetch more than requested, when convenient,
252 marking them as valid so we won't fetch them again. */
255 fetch_inferior_registers (ignored
)
262 ecp
= lynx_registers_addr();
264 for (regno
= 0; regno
< NUM_REGS
; regno
++)
266 int ptrace_fun
= PTRACE_PEEKTHREAD
;
268 #ifdef PTRACE_PEEKUSP
269 ptrace_fun
= regno
== SP_REGNUM
? PTRACE_PEEKUSP
: PTRACE_PEEKTHREAD
;
273 reg
= ptrace (ptrace_fun
, inferior_pid
,
274 (PTRACE_ARG3_TYPE
) (ecp
+ regmap
[regno
]), 0);
276 perror_with_name ("fetch_inferior_registers(PTRACE_PEEKTHREAD)");
278 *(unsigned long *)®isters
[REGISTER_BYTE (regno
)] = reg
;
282 /* Store our register values back into the inferior.
283 If REGNO is -1, do this for all registers.
284 Otherwise, REGNO specifies which register (so we can save time). */
287 store_inferior_registers (ignored
)
294 ecp
= lynx_registers_addr();
296 for (regno
= 0; regno
< NUM_REGS
; regno
++)
298 int ptrace_fun
= PTRACE_POKEUSER
;
300 #ifdef PTRACE_POKEUSP
301 ptrace_fun
= regno
== SP_REGNUM
? PTRACE_POKEUSP
: PTRACE_POKEUSER
;
304 reg
= *(unsigned long *)®isters
[REGISTER_BYTE (regno
)];
307 ptrace (ptrace_fun
, inferior_pid
,
308 (PTRACE_ARG3_TYPE
) (ecp
+ regmap
[regno
]), reg
);
310 perror_with_name ("PTRACE_POKEUSER");
314 /* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
315 in the NEW_SUN_PTRACE case.
316 It ought to be straightforward. But it appears that writing did
317 not write the data that I specified. I cannot understand where
318 it got the data that it actually did write. */
320 /* Copy LEN bytes from inferior's memory starting at MEMADDR
321 to debugger memory starting at MYADDR. */
324 read_inferior_memory (memaddr
, myaddr
, len
)
330 /* Round starting address down to longword boundary. */
331 register CORE_ADDR addr
= memaddr
& -sizeof (int);
332 /* Round ending address up; get number of longwords that makes. */
334 = (((memaddr
+ len
) - addr
) + sizeof (int) - 1) / sizeof (int);
335 /* Allocate buffer of that many longwords. */
336 register int *buffer
= (int *) alloca (count
* sizeof (int));
338 /* Read all the longwords */
339 for (i
= 0; i
< count
; i
++, addr
+= sizeof (int))
341 buffer
[i
] = ptrace (PTRACE_PEEKTEXT
, inferior_pid
, addr
, 0);
344 /* Copy appropriate bytes out of the buffer. */
345 memcpy (myaddr
, (char *) buffer
+ (memaddr
& (sizeof (int) - 1)), len
);
348 /* Copy LEN bytes of data from debugger memory at MYADDR
349 to inferior's memory at MEMADDR.
350 On failure (cannot write the inferior)
351 returns the value of errno. */
354 write_inferior_memory (memaddr
, myaddr
, len
)
360 /* Round starting address down to longword boundary. */
361 register CORE_ADDR addr
= memaddr
& -sizeof (int);
362 /* Round ending address up; get number of longwords that makes. */
364 = (((memaddr
+ len
) - addr
) + sizeof (int) - 1) / sizeof (int);
365 /* Allocate buffer of that many longwords. */
366 register int *buffer
= (int *) alloca (count
* sizeof (int));
369 /* Fill start and end extra bytes of buffer with existing memory data. */
371 buffer
[0] = ptrace (PTRACE_PEEKTEXT
, inferior_pid
, addr
, 0);
376 = ptrace (PTRACE_PEEKTEXT
, inferior_pid
,
377 addr
+ (count
- 1) * sizeof (int), 0);
380 /* Copy data to be written over corresponding part of buffer */
382 memcpy ((char *) buffer
+ (memaddr
& (sizeof (int) - 1)), myaddr
, len
);
384 /* Write the entire buffer. */
386 for (i
= 0; i
< count
; i
++, addr
+= sizeof (int))
391 ptrace (PTRACE_POKETEXT
, inferior_pid
, addr
, buffer
[i
]);
394 fprintf(stderr
, "ptrace (PTRACE_POKETEXT): errno=%d, inferior_pid=0x%x, addr=0x%x, buffer[i] = 0x%x\n", errno
, inferior_pid
, addr
, buffer
[i
]);
395 fprintf(stderr
, "Sleeping for 1 second\n");