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