]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/gdbserver/low-lynx.c
* coff-solib.c (coff_solib_add): Cast result of alloca().
[thirdparty/binutils-gdb.git] / 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.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include "server.h"
21 #include "frame.h"
22 #include "inferior.h"
23
24 #include <stdio.h>
25 #include <sys/param.h>
26 #include <sys/dir.h>
27 #define LYNXOS
28 #include <sys/mem.h>
29 #include <sys/signal.h>
30 #include <sys/file.h>
31 #include <sys/kernel.h>
32 #include <sys/itimer.h>
33 #include <sys/time.h>
34 #include <sys/resource.h>
35 #include <sys/proc.h>
36 #include <signal.h>
37 #include <sys/ioctl.h>
38 #include <sgtty.h>
39 #include <fcntl.h>
40 #include "/usr/include/wait.h"
41
42 char registers[REGISTER_BYTES];
43
44 #include <sys/ptrace.h>
45
46 /* Start an inferior process and returns its pid.
47 ALLARGS is a vector of program-name and args. */
48
49 int
50 create_inferior (program, allargs)
51 char *program;
52 char **allargs;
53 {
54 int pid;
55
56 pid = fork ();
57 if (pid < 0)
58 perror_with_name ("fork");
59
60 if (pid == 0)
61 {
62 int pgrp;
63
64 /* Switch child to it's own process group so that signals won't
65 directly affect gdbserver. */
66
67 pgrp = getpid();
68 setpgrp(0, pgrp);
69 ioctl (0, TIOCSPGRP, &pgrp);
70
71 ptrace (PTRACE_TRACEME);
72
73 execv (program, allargs);
74
75 fprintf (stderr, "GDBserver (process %d): Cannot exec %s: %s.\n",
76 getpid(), program,
77 errno < sys_nerr ? sys_errlist[errno] : "unknown error");
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 (PTRACE_KILL, inferior_pid, 0, 0);
93 wait (0);
94
95 inferior_pid = 0;
96 }
97
98 /* Wait for process, returns status */
99
100 unsigned char
101 mywait (status)
102 char *status;
103 {
104 int pid;
105 union wait w;
106
107 enable_async_io();
108
109 pid = wait (&w);
110
111 disable_async_io();
112
113 if (pid != PIDGET(inferior_pid))
114 perror_with_name ("wait");
115
116 inferior_pid = BUILDPID (inferior_pid, w.w_tid);
117
118 if (WIFEXITED (w))
119 {
120 fprintf (stderr, "\nChild exited with status %d\n", WEXITSTATUS (w));
121 fprintf (stderr, "GDBserver exiting\n");
122 exit (0);
123 }
124 else if (!WIFSTOPPED (w))
125 {
126 fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
127 *status = 'T';
128 return ((unsigned char) WTERMSIG (w));
129 }
130
131 fetch_inferior_registers (0);
132
133 *status = 'S';
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 ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
148 if (errno)
149 perror_with_name ("ptrace");
150 }
151
152 #undef offsetof
153 #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
154
155 /* Mapping between GDB register #s and offsets into econtext. Must be
156 consistent with REGISTER_NAMES macro in various tmXXX.h files. */
157
158 #define X(ENTRY)(offsetof(struct econtext, ENTRY))
159
160 #ifdef I386
161 /* Mappings from tm-i386v.h */
162
163 static int regmap[] =
164 {
165 X(eax),
166 X(ecx),
167 X(edx),
168 X(ebx),
169 X(esp), /* sp */
170 X(ebp), /* fp */
171 X(esi),
172 X(edi),
173 X(eip), /* pc */
174 X(flags), /* ps */
175 X(cs),
176 X(ss),
177 X(ds),
178 X(es),
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. */
182 };
183 #endif
184
185 #ifdef M68K
186 /* Mappings from tm-m68k.h */
187
188 static int regmap[] =
189 {
190 X(regs[0]), /* d0 */
191 X(regs[1]), /* d1 */
192 X(regs[2]), /* d2 */
193 X(regs[3]), /* d3 */
194 X(regs[4]), /* d4 */
195 X(regs[5]), /* d5 */
196 X(regs[6]), /* d6 */
197 X(regs[7]), /* d7 */
198 X(regs[8]), /* a0 */
199 X(regs[9]), /* a1 */
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 */
205 0, /* sp */
206 X(status), /* ps */
207 X(pc),
208
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 */
217
218 X(fcregs[0]), /* fpcontrol */
219 X(fcregs[1]), /* fpstatus */
220 X(fcregs[2]), /* fpiaddr */
221 X(ssw), /* fpcode */
222 X(fault), /* fpflags */
223 };
224 #endif
225
226 /* Return the offset relative to the start of the per-thread data to the
227 saved context block. */
228
229 static unsigned long
230 lynx_registers_addr()
231 {
232 CORE_ADDR stblock;
233 int ecpoff = offsetof(st_t, ecp);
234 CORE_ADDR ecp;
235
236 errno = 0;
237 stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, inferior_pid,
238 (PTRACE_ARG3_TYPE)0, 0);
239 if (errno)
240 perror_with_name ("PTRACE_THREADUSER");
241
242 ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, inferior_pid,
243 (PTRACE_ARG3_TYPE)ecpoff, 0);
244 if (errno)
245 perror_with_name ("lynx_registers_addr(PTRACE_PEEKTHREAD)");
246
247 return ecp - stblock;
248 }
249
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. */
253
254 void
255 fetch_inferior_registers (ignored)
256 int ignored;
257 {
258 int regno;
259 unsigned long reg;
260 unsigned long ecp;
261
262 ecp = lynx_registers_addr();
263
264 for (regno = 0; regno < NUM_REGS; regno++)
265 {
266 int ptrace_fun = PTRACE_PEEKTHREAD;
267
268 #ifdef PTRACE_PEEKUSP
269 ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
270 #endif
271
272 errno = 0;
273 reg = ptrace (ptrace_fun, inferior_pid,
274 (PTRACE_ARG3_TYPE) (ecp + regmap[regno]), 0);
275 if (errno)
276 perror_with_name ("fetch_inferior_registers(PTRACE_PEEKTHREAD)");
277
278 *(unsigned long *)&registers[REGISTER_BYTE (regno)] = reg;
279 }
280 }
281
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). */
285
286 void
287 store_inferior_registers (ignored)
288 int ignored;
289 {
290 int regno;
291 unsigned long reg;
292 unsigned long ecp;
293
294 ecp = lynx_registers_addr();
295
296 for (regno = 0; regno < NUM_REGS; regno++)
297 {
298 int ptrace_fun = PTRACE_POKEUSER;
299
300 #ifdef PTRACE_POKEUSP
301 ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
302 #endif
303
304 reg = *(unsigned long *)&registers[REGISTER_BYTE (regno)];
305
306 errno = 0;
307 ptrace (ptrace_fun, inferior_pid,
308 (PTRACE_ARG3_TYPE) (ecp + regmap[regno]), reg);
309 if (errno)
310 perror_with_name ("PTRACE_POKEUSER");
311 }
312 }
313
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. */
319
320 /* Copy LEN bytes from inferior's memory starting at MEMADDR
321 to debugger memory starting at MYADDR. */
322
323 void
324 read_inferior_memory (memaddr, myaddr, len)
325 CORE_ADDR memaddr;
326 char *myaddr;
327 int len;
328 {
329 register int i;
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. */
333 register int count
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));
337
338 /* Read all the longwords */
339 for (i = 0; i < count; i++, addr += sizeof (int))
340 {
341 buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
342 }
343
344 /* Copy appropriate bytes out of the buffer. */
345 memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
346 }
347
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. */
352
353 int
354 write_inferior_memory (memaddr, myaddr, len)
355 CORE_ADDR memaddr;
356 char *myaddr;
357 int len;
358 {
359 register int i;
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. */
363 register int count
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));
367 extern int errno;
368
369 /* Fill start and end extra bytes of buffer with existing memory data. */
370
371 buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
372
373 if (count > 1)
374 {
375 buffer[count - 1]
376 = ptrace (PTRACE_PEEKTEXT, inferior_pid,
377 addr + (count - 1) * sizeof (int), 0);
378 }
379
380 /* Copy data to be written over corresponding part of buffer */
381
382 memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
383
384 /* Write the entire buffer. */
385
386 for (i = 0; i < count; i++, addr += sizeof (int))
387 {
388 while (1)
389 {
390 errno = 0;
391 ptrace (PTRACE_POKETEXT, inferior_pid, addr, buffer[i]);
392 if (errno)
393 {
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");
396 sleep(1);
397 }
398 else
399 break;
400 }
401 }
402
403 return 0;
404 }