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