]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/gdbserver/low-lynx.c
import gdb-1999-07-07 post reformat
[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., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include "server.h"
22 #include "frame.h"
23 #include "inferior.h"
24
25 #include <stdio.h>
26 #include <sys/param.h>
27 #include <sys/dir.h>
28 #define LYNXOS
29 #include <sys/mem.h>
30 #include <sys/signal.h>
31 #include <sys/file.h>
32 #include <sys/kernel.h>
33 #ifndef __LYNXOS
34 #define __LYNXOS
35 #endif
36 #include <sys/itimer.h>
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <sys/proc.h>
40 #include <signal.h>
41 #include <sys/ioctl.h>
42 #include <sgtty.h>
43 #include <fcntl.h>
44 #include <sys/wait.h>
45 #include <sys/fpp.h>
46
47 char registers[REGISTER_BYTES];
48
49 #include <sys/ptrace.h>
50
51 /* Start an inferior process and returns its pid.
52 ALLARGS is a vector of program-name and args. */
53
54 int
55 create_inferior (program, allargs)
56 char *program;
57 char **allargs;
58 {
59 int pid;
60
61 pid = fork ();
62 if (pid < 0)
63 perror_with_name ("fork");
64
65 if (pid == 0)
66 {
67 int pgrp;
68
69 /* Switch child to it's own process group so that signals won't
70 directly affect gdbserver. */
71
72 pgrp = getpid ();
73 setpgrp (0, pgrp);
74 ioctl (0, TIOCSPGRP, &pgrp);
75
76 ptrace (PTRACE_TRACEME, 0, (PTRACE_ARG3_TYPE) 0, 0);
77
78 execv (program, allargs);
79
80 fprintf (stderr, "GDBserver (process %d): Cannot exec %s: %s.\n",
81 getpid (), program,
82 errno < sys_nerr ? sys_errlist[errno] : "unknown error");
83 fflush (stderr);
84 _exit (0177);
85 }
86
87 return pid;
88 }
89
90 /* Kill the inferior process. Make us have no inferior. */
91
92 void
93 kill_inferior ()
94 {
95 if (inferior_pid == 0)
96 return;
97 ptrace (PTRACE_KILL, inferior_pid, 0, 0);
98 wait (0);
99
100 inferior_pid = 0;
101 }
102
103 /* Return nonzero if the given thread is still alive. */
104 int
105 mythread_alive (pid)
106 int pid;
107 {
108 /* Arggh. Apparently pthread_kill only works for threads within
109 the process that calls pthread_kill.
110
111 We want to avoid the lynx signal extensions as they simply don't
112 map well to the generic gdb interface we want to keep.
113
114 All we want to do is determine if a particular thread is alive;
115 it appears as if we can just make a harmless thread specific
116 ptrace call to do that. */
117 return (ptrace (PTRACE_THREADUSER,
118 BUILDPID (PIDGET (inferior_pid), pid), 0, 0) != -1);
119 }
120
121 /* Wait for process, returns status */
122
123 unsigned char
124 mywait (status)
125 char *status;
126 {
127 int pid;
128 union wait w;
129
130 while (1)
131 {
132 enable_async_io ();
133
134 pid = wait (&w);
135
136 disable_async_io ();
137
138 if (pid != PIDGET (inferior_pid))
139 perror_with_name ("wait");
140
141 thread_from_wait = w.w_tid;
142 inferior_pid = BUILDPID (inferior_pid, w.w_tid);
143
144 if (WIFSTOPPED (w)
145 && WSTOPSIG (w) == SIGTRAP)
146 {
147 int realsig;
148
149 realsig = ptrace (PTRACE_GETTRACESIG, inferior_pid,
150 (PTRACE_ARG3_TYPE) 0, 0);
151
152 if (realsig == SIGNEWTHREAD)
153 {
154 /* It's a new thread notification. Nothing to do here since
155 the machine independent code in wait_for_inferior will
156 add the thread to the thread list and restart the thread
157 when pid != inferior_pid and pid is not in the thread list.
158 We don't even want to muck with realsig -- the code in
159 wait_for_inferior expects SIGTRAP. */
160 ;
161 }
162 }
163 break;
164 }
165
166 if (WIFEXITED (w))
167 {
168 *status = 'W';
169 return ((unsigned char) WEXITSTATUS (w));
170 }
171 else if (!WIFSTOPPED (w))
172 {
173 *status = 'X';
174 return ((unsigned char) WTERMSIG (w));
175 }
176
177 fetch_inferior_registers (0);
178
179 *status = 'T';
180 return ((unsigned char) WSTOPSIG (w));
181 }
182
183 /* Resume execution of the inferior process.
184 If STEP is nonzero, single-step it.
185 If SIGNAL is nonzero, give it that signal. */
186
187 void
188 myresume (step, signal)
189 int step;
190 int signal;
191 {
192 errno = 0;
193 ptrace (step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT,
194 BUILDPID (inferior_pid, cont_thread == -1 ? 0 : cont_thread),
195 1, signal);
196 if (errno)
197 perror_with_name ("ptrace");
198 }
199
200 #undef offsetof
201 #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
202
203 /* Mapping between GDB register #s and offsets into econtext. Must be
204 consistent with REGISTER_NAMES macro in various tmXXX.h files. */
205
206 #define X(ENTRY)(offsetof(struct econtext, ENTRY))
207
208 #ifdef I386
209 /* Mappings from tm-i386v.h */
210
211 static int regmap[] =
212 {
213 X (eax),
214 X (ecx),
215 X (edx),
216 X (ebx),
217 X (esp), /* sp */
218 X (ebp), /* fp */
219 X (esi),
220 X (edi),
221 X (eip), /* pc */
222 X (flags), /* ps */
223 X (cs),
224 X (ss),
225 X (ds),
226 X (es),
227 X (ecode), /* Lynx doesn't give us either fs or gs, so */
228 X (fault), /* we just substitute these two in the hopes
229 that they are useful. */
230 };
231 #endif
232
233 #ifdef M68K
234 /* Mappings from tm-m68k.h */
235
236 static int regmap[] =
237 {
238 X (regs[0]), /* d0 */
239 X (regs[1]), /* d1 */
240 X (regs[2]), /* d2 */
241 X (regs[3]), /* d3 */
242 X (regs[4]), /* d4 */
243 X (regs[5]), /* d5 */
244 X (regs[6]), /* d6 */
245 X (regs[7]), /* d7 */
246 X (regs[8]), /* a0 */
247 X (regs[9]), /* a1 */
248 X (regs[10]), /* a2 */
249 X (regs[11]), /* a3 */
250 X (regs[12]), /* a4 */
251 X (regs[13]), /* a5 */
252 X (regs[14]), /* fp */
253 0, /* sp */
254 X (status), /* ps */
255 X (pc),
256
257 X (fregs[0 * 3]), /* fp0 */
258 X (fregs[1 * 3]), /* fp1 */
259 X (fregs[2 * 3]), /* fp2 */
260 X (fregs[3 * 3]), /* fp3 */
261 X (fregs[4 * 3]), /* fp4 */
262 X (fregs[5 * 3]), /* fp5 */
263 X (fregs[6 * 3]), /* fp6 */
264 X (fregs[7 * 3]), /* fp7 */
265
266 X (fcregs[0]), /* fpcontrol */
267 X (fcregs[1]), /* fpstatus */
268 X (fcregs[2]), /* fpiaddr */
269 X (ssw), /* fpcode */
270 X (fault), /* fpflags */
271 };
272 #endif
273
274 #ifdef SPARC
275 /* Mappings from tm-sparc.h */
276
277 #define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
278
279 static int regmap[] =
280 {
281 -1, /* g0 */
282 X (g1),
283 X (g2),
284 X (g3),
285 X (g4),
286 -1, /* g5->g7 aren't saved by Lynx */
287 -1,
288 -1,
289
290 X (o[0]),
291 X (o[1]),
292 X (o[2]),
293 X (o[3]),
294 X (o[4]),
295 X (o[5]),
296 X (o[6]), /* sp */
297 X (o[7]), /* ra */
298
299 -1, -1, -1, -1, -1, -1, -1, -1, /* l0 -> l7 */
300
301 -1, -1, -1, -1, -1, -1, -1, -1, /* i0 -> i7 */
302
303 FX (f.fregs[0]), /* f0 */
304 FX (f.fregs[1]),
305 FX (f.fregs[2]),
306 FX (f.fregs[3]),
307 FX (f.fregs[4]),
308 FX (f.fregs[5]),
309 FX (f.fregs[6]),
310 FX (f.fregs[7]),
311 FX (f.fregs[8]),
312 FX (f.fregs[9]),
313 FX (f.fregs[10]),
314 FX (f.fregs[11]),
315 FX (f.fregs[12]),
316 FX (f.fregs[13]),
317 FX (f.fregs[14]),
318 FX (f.fregs[15]),
319 FX (f.fregs[16]),
320 FX (f.fregs[17]),
321 FX (f.fregs[18]),
322 FX (f.fregs[19]),
323 FX (f.fregs[20]),
324 FX (f.fregs[21]),
325 FX (f.fregs[22]),
326 FX (f.fregs[23]),
327 FX (f.fregs[24]),
328 FX (f.fregs[25]),
329 FX (f.fregs[26]),
330 FX (f.fregs[27]),
331 FX (f.fregs[28]),
332 FX (f.fregs[29]),
333 FX (f.fregs[30]),
334 FX (f.fregs[31]),
335
336 X (y),
337 X (psr),
338 X (wim),
339 X (tbr),
340 X (pc),
341 X (npc),
342 FX (fsr), /* fpsr */
343 -1, /* cpsr */
344 };
345 #endif
346
347 #ifdef SPARC
348
349 /* This routine handles some oddball cases for Sparc registers and LynxOS.
350 In partucular, it causes refs to G0, g5->7, and all fp regs to return zero.
351 It also handles knows where to find the I & L regs on the stack. */
352
353 void
354 fetch_inferior_registers (regno)
355 int regno;
356 {
357 #if 0
358 int whatregs = 0;
359
360 #define WHATREGS_FLOAT 1
361 #define WHATREGS_GEN 2
362 #define WHATREGS_STACK 4
363
364 if (regno == -1)
365 whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
366 else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
367 whatregs = WHATREGS_STACK;
368 else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
369 whatregs = WHATREGS_FLOAT;
370 else
371 whatregs = WHATREGS_GEN;
372
373 if (whatregs & WHATREGS_GEN)
374 {
375 struct econtext ec; /* general regs */
376 char buf[MAX_REGISTER_RAW_SIZE];
377 int retval;
378 int i;
379
380 errno = 0;
381 retval = ptrace (PTRACE_GETREGS,
382 BUILDPID (inferior_pid, general_thread),
383 (PTRACE_ARG3_TYPE) & ec,
384 0);
385 if (errno)
386 perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
387
388 memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM));
389 supply_register (G0_REGNUM, buf);
390 supply_register (TBR_REGNUM, (char *) &ec.tbr);
391
392 memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &ec.g1,
393 4 * REGISTER_RAW_SIZE (G1_REGNUM));
394 for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++)
395 register_valid[i] = 1;
396
397 supply_register (PS_REGNUM, (char *) &ec.psr);
398 supply_register (Y_REGNUM, (char *) &ec.y);
399 supply_register (PC_REGNUM, (char *) &ec.pc);
400 supply_register (NPC_REGNUM, (char *) &ec.npc);
401 supply_register (WIM_REGNUM, (char *) &ec.wim);
402
403 memcpy (&registers[REGISTER_BYTE (O0_REGNUM)], ec.o,
404 8 * REGISTER_RAW_SIZE (O0_REGNUM));
405 for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++)
406 register_valid[i] = 1;
407 }
408
409 if (whatregs & WHATREGS_STACK)
410 {
411 CORE_ADDR sp;
412 int i;
413
414 sp = read_register (SP_REGNUM);
415
416 target_xfer_memory (sp + FRAME_SAVED_I0,
417 &registers[REGISTER_BYTE (I0_REGNUM)],
418 8 * REGISTER_RAW_SIZE (I0_REGNUM), 0);
419 for (i = I0_REGNUM; i <= I7_REGNUM; i++)
420 register_valid[i] = 1;
421
422 target_xfer_memory (sp + FRAME_SAVED_L0,
423 &registers[REGISTER_BYTE (L0_REGNUM)],
424 8 * REGISTER_RAW_SIZE (L0_REGNUM), 0);
425 for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++)
426 register_valid[i] = 1;
427 }
428
429 if (whatregs & WHATREGS_FLOAT)
430 {
431 struct fcontext fc; /* fp regs */
432 int retval;
433 int i;
434
435 errno = 0;
436 retval = ptrace (PTRACE_GETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) & fc,
437 0);
438 if (errno)
439 perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
440
441 memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs,
442 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
443 for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
444 register_valid[i] = 1;
445
446 supply_register (FPS_REGNUM, (char *) &fc.fsr);
447 }
448 #endif
449 }
450
451 /* This routine handles storing of the I & L regs for the Sparc. The trick
452 here is that they actually live on the stack. The really tricky part is
453 that when changing the stack pointer, the I & L regs must be written to
454 where the new SP points, otherwise the regs will be incorrect when the
455 process is started up again. We assume that the I & L regs are valid at
456 this point. */
457
458 void
459 store_inferior_registers (regno)
460 int regno;
461 {
462 #if 0
463 int whatregs = 0;
464
465 if (regno == -1)
466 whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
467 else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
468 whatregs = WHATREGS_STACK;
469 else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
470 whatregs = WHATREGS_FLOAT;
471 else if (regno == SP_REGNUM)
472 whatregs = WHATREGS_STACK | WHATREGS_GEN;
473 else
474 whatregs = WHATREGS_GEN;
475
476 if (whatregs & WHATREGS_GEN)
477 {
478 struct econtext ec; /* general regs */
479 int retval;
480
481 ec.tbr = read_register (TBR_REGNUM);
482 memcpy (&ec.g1, &registers[REGISTER_BYTE (G1_REGNUM)],
483 4 * REGISTER_RAW_SIZE (G1_REGNUM));
484
485 ec.psr = read_register (PS_REGNUM);
486 ec.y = read_register (Y_REGNUM);
487 ec.pc = read_register (PC_REGNUM);
488 ec.npc = read_register (NPC_REGNUM);
489 ec.wim = read_register (WIM_REGNUM);
490
491 memcpy (ec.o, &registers[REGISTER_BYTE (O0_REGNUM)],
492 8 * REGISTER_RAW_SIZE (O0_REGNUM));
493
494 errno = 0;
495 retval = ptrace (PTRACE_SETREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) & ec,
496 0);
497 if (errno)
498 perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
499 }
500
501 if (whatregs & WHATREGS_STACK)
502 {
503 int regoffset;
504 CORE_ADDR sp;
505
506 sp = read_register (SP_REGNUM);
507
508 if (regno == -1 || regno == SP_REGNUM)
509 {
510 if (!register_valid[L0_REGNUM + 5])
511 abort ();
512 target_xfer_memory (sp + FRAME_SAVED_I0,
513 &registers[REGISTER_BYTE (I0_REGNUM)],
514 8 * REGISTER_RAW_SIZE (I0_REGNUM), 1);
515
516 target_xfer_memory (sp + FRAME_SAVED_L0,
517 &registers[REGISTER_BYTE (L0_REGNUM)],
518 8 * REGISTER_RAW_SIZE (L0_REGNUM), 1);
519 }
520 else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
521 {
522 if (!register_valid[regno])
523 abort ();
524 if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
525 regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
526 + FRAME_SAVED_L0;
527 else
528 regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM)
529 + FRAME_SAVED_I0;
530 target_xfer_memory (sp + regoffset, &registers[REGISTER_BYTE (regno)],
531 REGISTER_RAW_SIZE (regno), 1);
532 }
533 }
534
535 if (whatregs & WHATREGS_FLOAT)
536 {
537 struct fcontext fc; /* fp regs */
538 int retval;
539
540 /* We read fcontext first so that we can get good values for fq_t... */
541 errno = 0;
542 retval = ptrace (PTRACE_GETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) & fc,
543 0);
544 if (errno)
545 perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
546
547 memcpy (fc.f.fregs, &registers[REGISTER_BYTE (FP0_REGNUM)],
548 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
549
550 fc.fsr = read_register (FPS_REGNUM);
551
552 errno = 0;
553 retval = ptrace (PTRACE_SETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) & fc,
554 0);
555 if (errno)
556 perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
557 }
558 #endif
559 }
560 #endif /* SPARC */
561
562 #ifndef SPARC
563
564 /* Return the offset relative to the start of the per-thread data to the
565 saved context block. */
566
567 static unsigned long
568 lynx_registers_addr ()
569 {
570 CORE_ADDR stblock;
571 int ecpoff = offsetof (st_t, ecp);
572 CORE_ADDR ecp;
573
574 errno = 0;
575 stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, BUILDPID (inferior_pid, general_thread),
576 (PTRACE_ARG3_TYPE) 0, 0);
577 if (errno)
578 perror_with_name ("PTRACE_THREADUSER");
579
580 ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, BUILDPID (inferior_pid, general_thread),
581 (PTRACE_ARG3_TYPE) ecpoff, 0);
582 if (errno)
583 perror_with_name ("lynx_registers_addr(PTRACE_PEEKTHREAD)");
584
585 return ecp - stblock;
586 }
587
588 /* Fetch one or more registers from the inferior. REGNO == -1 to get
589 them all. We actually fetch more than requested, when convenient,
590 marking them as valid so we won't fetch them again. */
591
592 void
593 fetch_inferior_registers (ignored)
594 int ignored;
595 {
596 int regno;
597 unsigned long reg;
598 unsigned long ecp;
599
600 ecp = lynx_registers_addr ();
601
602 for (regno = 0; regno < NUM_REGS; regno++)
603 {
604 int ptrace_fun = PTRACE_PEEKTHREAD;
605
606 #ifdef PTRACE_PEEKUSP
607 ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
608 #endif
609
610 errno = 0;
611 reg = ptrace (ptrace_fun, BUILDPID (inferior_pid, general_thread),
612 (PTRACE_ARG3_TYPE) (ecp + regmap[regno]), 0);
613 if (errno)
614 perror_with_name ("fetch_inferior_registers(PTRACE_PEEKTHREAD)");
615
616 *(unsigned long *) &registers[REGISTER_BYTE (regno)] = reg;
617 }
618 }
619
620 /* Store our register values back into the inferior.
621 If REGNO is -1, do this for all registers.
622 Otherwise, REGNO specifies which register (so we can save time). */
623
624 void
625 store_inferior_registers (ignored)
626 int ignored;
627 {
628 int regno;
629 unsigned long reg;
630 unsigned long ecp;
631
632 ecp = lynx_registers_addr ();
633
634 for (regno = 0; regno < NUM_REGS; regno++)
635 {
636 int ptrace_fun = PTRACE_POKEUSER;
637
638 #ifdef PTRACE_POKEUSP
639 ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
640 #endif
641
642 reg = *(unsigned long *) &registers[REGISTER_BYTE (regno)];
643
644 errno = 0;
645 ptrace (ptrace_fun, BUILDPID (inferior_pid, general_thread),
646 (PTRACE_ARG3_TYPE) (ecp + regmap[regno]), reg);
647 if (errno)
648 perror_with_name ("PTRACE_POKEUSER");
649 }
650 }
651
652 #endif /* ! SPARC */
653
654 /* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
655 in the NEW_SUN_PTRACE case.
656 It ought to be straightforward. But it appears that writing did
657 not write the data that I specified. I cannot understand where
658 it got the data that it actually did write. */
659
660 /* Copy LEN bytes from inferior's memory starting at MEMADDR
661 to debugger memory starting at MYADDR. */
662
663 void
664 read_inferior_memory (memaddr, myaddr, len)
665 CORE_ADDR memaddr;
666 char *myaddr;
667 int len;
668 {
669 register int i;
670 /* Round starting address down to longword boundary. */
671 register CORE_ADDR addr = memaddr & -sizeof (int);
672 /* Round ending address up; get number of longwords that makes. */
673 register int count
674 = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
675 /* Allocate buffer of that many longwords. */
676 register int *buffer = (int *) alloca (count * sizeof (int));
677
678 /* Read all the longwords */
679 for (i = 0; i < count; i++, addr += sizeof (int))
680 {
681 buffer[i] = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread), addr, 0);
682 }
683
684 /* Copy appropriate bytes out of the buffer. */
685 memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
686 }
687
688 /* Copy LEN bytes of data from debugger memory at MYADDR
689 to inferior's memory at MEMADDR.
690 On failure (cannot write the inferior)
691 returns the value of errno. */
692
693 int
694 write_inferior_memory (memaddr, myaddr, len)
695 CORE_ADDR memaddr;
696 char *myaddr;
697 int len;
698 {
699 register int i;
700 /* Round starting address down to longword boundary. */
701 register CORE_ADDR addr = memaddr & -sizeof (int);
702 /* Round ending address up; get number of longwords that makes. */
703 register int count
704 = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
705 /* Allocate buffer of that many longwords. */
706 register int *buffer = (int *) alloca (count * sizeof (int));
707 extern int errno;
708
709 /* Fill start and end extra bytes of buffer with existing memory data. */
710
711 buffer[0] = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread), addr, 0);
712
713 if (count > 1)
714 {
715 buffer[count - 1]
716 = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread),
717 addr + (count - 1) * sizeof (int), 0);
718 }
719
720 /* Copy data to be written over corresponding part of buffer */
721
722 memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
723
724 /* Write the entire buffer. */
725
726 for (i = 0; i < count; i++, addr += sizeof (int))
727 {
728 while (1)
729 {
730 errno = 0;
731 ptrace (PTRACE_POKETEXT, BUILDPID (inferior_pid, general_thread), addr, buffer[i]);
732 if (errno)
733 {
734 fprintf (stderr, "\
735 ptrace (PTRACE_POKETEXT): errno=%d, pid=0x%x, addr=0x%x, buffer[i] = 0x%x\n",
736 errno, BUILDPID (inferior_pid, general_thread),
737 addr, buffer[i]);
738 fprintf (stderr, "Sleeping for 1 second\n");
739 sleep (1);
740 }
741 else
742 break;
743 }
744 }
745
746 return 0;
747 }