Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / gdb / 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 }