2002-02-05 Daniel Jacobowitz <drow@mvista.com>
[binutils-gdb.git] / gdb / gdbserver / linux-low.c
1 /* Low level interface to ptrace, for the remote server for GDB.
2 Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "server.h"
23 #include <sys/wait.h>
24 #include "frame.h"
25 #include "inferior.h"
26
27 #include <stdio.h>
28 #include <sys/param.h>
29 #include <sys/dir.h>
30 #include <sys/ptrace.h>
31 #include <sys/user.h>
32 #include <signal.h>
33 #include <sys/ioctl.h>
34 #include <fcntl.h>
35 #include <string.h>
36
37 /***************Begin MY defs*********************/
38 static char my_registers[REGISTER_BYTES];
39 char *registers = my_registers;
40 /***************End MY defs*********************/
41
42 #ifdef HAVE_SYS_REG_H
43 #include <sys/reg.h>
44 #endif
45
46 /* Default the type of the ptrace transfer to int. */
47 #ifndef PTRACE_XFER_TYPE
48 #define PTRACE_XFER_TYPE int
49 #endif
50
51 extern int errno;
52
53 static void initialize_arch (void);
54
55 /* Start an inferior process and returns its pid.
56 ALLARGS is a vector of program-name and args. */
57
58 int
59 create_inferior (char *program, char **allargs)
60 {
61 int pid;
62
63 pid = fork ();
64 if (pid < 0)
65 perror_with_name ("fork");
66
67 if (pid == 0)
68 {
69 ptrace (PTRACE_TRACEME, 0, 0, 0);
70
71 execv (program, allargs);
72
73 fprintf (stderr, "Cannot exec %s: %s.\n", program,
74 strerror (errno));
75 fflush (stderr);
76 _exit (0177);
77 }
78
79 return pid;
80 }
81
82 /* Attach to an inferior process. */
83
84 int
85 myattach (int pid)
86 {
87 if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
88 {
89 fprintf (stderr, "Cannot attach to process %d: %s (%d)\n", pid,
90 errno < sys_nerr ? sys_errlist[errno] : "unknown error",
91 errno);
92 fflush (stderr);
93 _exit (0177);
94 }
95
96 return 0;
97 }
98
99 /* Kill the inferior process. Make us have no inferior. */
100
101 void
102 kill_inferior (void)
103 {
104 if (inferior_pid == 0)
105 return;
106 ptrace (PTRACE_KILL, inferior_pid, 0, 0);
107 wait (0);
108 /*************inferior_died ();****VK**************/
109 }
110
111 /* Return nonzero if the given thread is still alive. */
112 int
113 mythread_alive (int pid)
114 {
115 return 1;
116 }
117
118 /* Wait for process, returns status */
119
120 unsigned char
121 mywait (char *status)
122 {
123 int pid;
124 union wait w;
125
126 enable_async_io ();
127 pid = waitpid (inferior_pid, &w, 0);
128 disable_async_io ();
129 if (pid != inferior_pid)
130 perror_with_name ("wait");
131
132 if (WIFEXITED (w))
133 {
134 fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
135 *status = 'W';
136 return ((unsigned char) WEXITSTATUS (w));
137 }
138 else if (!WIFSTOPPED (w))
139 {
140 fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
141 *status = 'X';
142 return ((unsigned char) WTERMSIG (w));
143 }
144
145 fetch_inferior_registers (0);
146
147 *status = 'T';
148 return ((unsigned char) WSTOPSIG (w));
149 }
150
151 /* Resume execution of the inferior process.
152 If STEP is nonzero, single-step it.
153 If SIGNAL is nonzero, give it that signal. */
154
155 void
156 myresume (int step, int signal)
157 {
158 errno = 0;
159 ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
160 if (errno)
161 perror_with_name ("ptrace");
162 }
163
164
165 #if !defined (offsetof)
166 #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
167 #endif
168
169 /* U_REGS_OFFSET is the offset of the registers within the u area. */
170 #if !defined (U_REGS_OFFSET)
171 #define U_REGS_OFFSET \
172 ptrace (PT_READ_U, inferior_pid, \
173 (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
174 - KERNEL_U_ADDR
175 #endif
176
177 #ifdef I386_GNULINUX_TARGET
178 /* This module only supports access to the general purpose registers.
179 Adjust the relevant constants accordingly.
180
181 FIXME: kettenis/2001-03-28: We should really use PTRACE_GETREGS to
182 get at the registers. Better yet, we should try to share code with
183 i386-linux-nat.c. */
184 #undef NUM_FREGS
185 #define NUM_FREGS 0
186 #undef NUM_REGS
187 #define NUM_REGS NUM_GREGS
188
189 /* This stuff comes from i386-tdep.c. */
190
191 /* i386_register_byte[i] is the offset into the register file of the
192 start of register number i. We initialize this from
193 i386_register_raw_size. */
194 int i386_register_byte[MAX_NUM_REGS];
195
196 /* i386_register_raw_size[i] is the number of bytes of storage in
197 GDB's register array occupied by register i. */
198 int i386_register_raw_size[MAX_NUM_REGS] = {
199 4, 4, 4, 4,
200 4, 4, 4, 4,
201 4, 4, 4, 4,
202 4, 4, 4, 4,
203 10, 10, 10, 10,
204 10, 10, 10, 10,
205 4, 4, 4, 4,
206 4, 4, 4, 4,
207 16, 16, 16, 16,
208 16, 16, 16, 16,
209 4
210 };
211
212 static void
213 initialize_arch (void)
214 {
215 /* Initialize the table saying where each register starts in the
216 register file. */
217 {
218 int i, offset;
219
220 offset = 0;
221 for (i = 0; i < MAX_NUM_REGS; i++)
222 {
223 i386_register_byte[i] = offset;
224 offset += i386_register_raw_size[i];
225 }
226 }
227 }
228
229 /* This stuff comes from i386-linux-nat.c. */
230
231 /* Mapping between the general-purpose registers in `struct user'
232 format and GDB's register array layout. */
233 static int regmap[] =
234 {
235 EAX, ECX, EDX, EBX,
236 UESP, EBP, ESI, EDI,
237 EIP, EFL, CS, SS,
238 DS, ES, FS, GS
239 };
240
241 /* Return the address of register REGNUM. BLOCKEND is the value of
242 u.u_ar0, which should point to the registers. */
243
244 CORE_ADDR
245 register_u_addr (CORE_ADDR blockend, int regnum)
246 {
247 return (blockend + 4 * regmap[regnum]);
248 }
249 #elif defined(TARGET_M68K)
250 static void
251 initialize_arch (void)
252 {
253 return;
254 }
255
256 /* This table must line up with REGISTER_NAMES in tm-m68k.h */
257 static int regmap[] =
258 {
259 #ifdef PT_D0
260 PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
261 PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
262 PT_SR, PT_PC,
263 #else
264 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15,
265 17, 18,
266 #endif
267 #ifdef PT_FP0
268 PT_FP0, PT_FP1, PT_FP2, PT_FP3, PT_FP4, PT_FP5, PT_FP6, PT_FP7,
269 PT_FPCR, PT_FPSR, PT_FPIAR
270 #else
271 21, 24, 27, 30, 33, 36, 39, 42, 45, 46, 47
272 #endif
273 };
274
275 /* BLOCKEND is the value of u.u_ar0, and points to the place where GS
276 is stored. */
277
278 int
279 m68k_linux_register_u_addr (int blockend, int regnum)
280 {
281 return (blockend + 4 * regmap[regnum]);
282 }
283 #elif defined(IA64_GNULINUX_TARGET)
284 #undef NUM_FREGS
285 #define NUM_FREGS 0
286
287 #include <asm/ptrace_offsets.h>
288
289 static int u_offsets[] =
290 {
291 /* general registers */
292 -1, /* gr0 not available; i.e, it's always zero */
293 PT_R1,
294 PT_R2,
295 PT_R3,
296 PT_R4,
297 PT_R5,
298 PT_R6,
299 PT_R7,
300 PT_R8,
301 PT_R9,
302 PT_R10,
303 PT_R11,
304 PT_R12,
305 PT_R13,
306 PT_R14,
307 PT_R15,
308 PT_R16,
309 PT_R17,
310 PT_R18,
311 PT_R19,
312 PT_R20,
313 PT_R21,
314 PT_R22,
315 PT_R23,
316 PT_R24,
317 PT_R25,
318 PT_R26,
319 PT_R27,
320 PT_R28,
321 PT_R29,
322 PT_R30,
323 PT_R31,
324 /* gr32 through gr127 not directly available via the ptrace interface */
325 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
326 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
327 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
328 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
329 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
330 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
331 /* Floating point registers */
332 -1, -1, /* f0 and f1 not available (f0 is +0.0 and f1 is +1.0) */
333 PT_F2,
334 PT_F3,
335 PT_F4,
336 PT_F5,
337 PT_F6,
338 PT_F7,
339 PT_F8,
340 PT_F9,
341 PT_F10,
342 PT_F11,
343 PT_F12,
344 PT_F13,
345 PT_F14,
346 PT_F15,
347 PT_F16,
348 PT_F17,
349 PT_F18,
350 PT_F19,
351 PT_F20,
352 PT_F21,
353 PT_F22,
354 PT_F23,
355 PT_F24,
356 PT_F25,
357 PT_F26,
358 PT_F27,
359 PT_F28,
360 PT_F29,
361 PT_F30,
362 PT_F31,
363 PT_F32,
364 PT_F33,
365 PT_F34,
366 PT_F35,
367 PT_F36,
368 PT_F37,
369 PT_F38,
370 PT_F39,
371 PT_F40,
372 PT_F41,
373 PT_F42,
374 PT_F43,
375 PT_F44,
376 PT_F45,
377 PT_F46,
378 PT_F47,
379 PT_F48,
380 PT_F49,
381 PT_F50,
382 PT_F51,
383 PT_F52,
384 PT_F53,
385 PT_F54,
386 PT_F55,
387 PT_F56,
388 PT_F57,
389 PT_F58,
390 PT_F59,
391 PT_F60,
392 PT_F61,
393 PT_F62,
394 PT_F63,
395 PT_F64,
396 PT_F65,
397 PT_F66,
398 PT_F67,
399 PT_F68,
400 PT_F69,
401 PT_F70,
402 PT_F71,
403 PT_F72,
404 PT_F73,
405 PT_F74,
406 PT_F75,
407 PT_F76,
408 PT_F77,
409 PT_F78,
410 PT_F79,
411 PT_F80,
412 PT_F81,
413 PT_F82,
414 PT_F83,
415 PT_F84,
416 PT_F85,
417 PT_F86,
418 PT_F87,
419 PT_F88,
420 PT_F89,
421 PT_F90,
422 PT_F91,
423 PT_F92,
424 PT_F93,
425 PT_F94,
426 PT_F95,
427 PT_F96,
428 PT_F97,
429 PT_F98,
430 PT_F99,
431 PT_F100,
432 PT_F101,
433 PT_F102,
434 PT_F103,
435 PT_F104,
436 PT_F105,
437 PT_F106,
438 PT_F107,
439 PT_F108,
440 PT_F109,
441 PT_F110,
442 PT_F111,
443 PT_F112,
444 PT_F113,
445 PT_F114,
446 PT_F115,
447 PT_F116,
448 PT_F117,
449 PT_F118,
450 PT_F119,
451 PT_F120,
452 PT_F121,
453 PT_F122,
454 PT_F123,
455 PT_F124,
456 PT_F125,
457 PT_F126,
458 PT_F127,
459 /* predicate registers - we don't fetch these individually */
460 -1, -1, -1, -1, -1, -1, -1, -1,
461 -1, -1, -1, -1, -1, -1, -1, -1,
462 -1, -1, -1, -1, -1, -1, -1, -1,
463 -1, -1, -1, -1, -1, -1, -1, -1,
464 -1, -1, -1, -1, -1, -1, -1, -1,
465 -1, -1, -1, -1, -1, -1, -1, -1,
466 -1, -1, -1, -1, -1, -1, -1, -1,
467 -1, -1, -1, -1, -1, -1, -1, -1,
468 /* branch registers */
469 PT_B0,
470 PT_B1,
471 PT_B2,
472 PT_B3,
473 PT_B4,
474 PT_B5,
475 PT_B6,
476 PT_B7,
477 /* virtual frame pointer and virtual return address pointer */
478 -1, -1,
479 /* other registers */
480 PT_PR,
481 PT_CR_IIP, /* ip */
482 PT_CR_IPSR, /* psr */
483 PT_CFM, /* cfm */
484 /* kernel registers not visible via ptrace interface (?) */
485 -1, -1, -1, -1, -1, -1, -1, -1,
486 /* hole */
487 -1, -1, -1, -1, -1, -1, -1, -1,
488 PT_AR_RSC,
489 PT_AR_BSP,
490 PT_AR_BSPSTORE,
491 PT_AR_RNAT,
492 -1,
493 -1, /* Not available: FCR, IA32 floating control register */
494 -1, -1,
495 -1, /* Not available: EFLAG */
496 -1, /* Not available: CSD */
497 -1, /* Not available: SSD */
498 -1, /* Not available: CFLG */
499 -1, /* Not available: FSR */
500 -1, /* Not available: FIR */
501 -1, /* Not available: FDR */
502 -1,
503 PT_AR_CCV,
504 -1, -1, -1,
505 PT_AR_UNAT,
506 -1, -1, -1,
507 PT_AR_FPSR,
508 -1, -1, -1,
509 -1, /* Not available: ITC */
510 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
511 -1, -1, -1, -1, -1, -1, -1, -1, -1,
512 PT_AR_PFS,
513 PT_AR_LC,
514 -1, /* Not available: EC, the Epilog Count register */
515 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
516 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
517 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
518 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
519 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
520 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
521 -1,
522 /* nat bits - not fetched directly; instead we obtain these bits from
523 either rnat or unat or from memory. */
524 -1, -1, -1, -1, -1, -1, -1, -1,
525 -1, -1, -1, -1, -1, -1, -1, -1,
526 -1, -1, -1, -1, -1, -1, -1, -1,
527 -1, -1, -1, -1, -1, -1, -1, -1,
528 -1, -1, -1, -1, -1, -1, -1, -1,
529 -1, -1, -1, -1, -1, -1, -1, -1,
530 -1, -1, -1, -1, -1, -1, -1, -1,
531 -1, -1, -1, -1, -1, -1, -1, -1,
532 -1, -1, -1, -1, -1, -1, -1, -1,
533 -1, -1, -1, -1, -1, -1, -1, -1,
534 -1, -1, -1, -1, -1, -1, -1, -1,
535 -1, -1, -1, -1, -1, -1, -1, -1,
536 -1, -1, -1, -1, -1, -1, -1, -1,
537 -1, -1, -1, -1, -1, -1, -1, -1,
538 -1, -1, -1, -1, -1, -1, -1, -1,
539 -1, -1, -1, -1, -1, -1, -1, -1,
540 };
541
542 int
543 ia64_register_u_addr (int blockend, int regnum)
544 {
545 int addr;
546
547 if (regnum < 0 || regnum >= NUM_REGS)
548 error ("Invalid register number %d.", regnum);
549
550 addr = u_offsets[regnum];
551 if (addr == -1)
552 addr = 0;
553
554 return addr;
555 }
556
557 static void
558 initialize_arch (void)
559 {
560 return;
561 }
562
563 #elif defined(ARM_GNULINUX_TARGET)
564 int arm_register_u_addr(blockend, regnum)
565 int blockend;
566 int regnum;
567 {
568 return blockend + REGISTER_BYTE(regnum);
569 }
570
571 static void
572 initialize_arch ()
573 {
574 }
575 #endif
576
577 CORE_ADDR
578 register_addr (int regno, CORE_ADDR blockend)
579 {
580 CORE_ADDR addr;
581
582 if (regno < 0 || regno >= NUM_REGS)
583 error ("Invalid register number %d.", regno);
584
585 REGISTER_U_ADDR (addr, blockend, regno);
586
587 return addr;
588 }
589
590 /* Fetch one register. */
591
592 static void
593 fetch_register (int regno)
594 {
595 CORE_ADDR regaddr;
596 register int i;
597
598 /* Offset of registers within the u area. */
599 unsigned int offset;
600
601 offset = U_REGS_OFFSET;
602
603 regaddr = register_addr (regno, offset);
604 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
605 {
606 errno = 0;
607 *(PTRACE_XFER_TYPE *) &registers[REGISTER_BYTE (regno) + i] =
608 ptrace (PTRACE_PEEKUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, 0);
609 regaddr += sizeof (PTRACE_XFER_TYPE);
610 if (errno != 0)
611 {
612 /* Warning, not error, in case we are attached; sometimes the
613 kernel doesn't let us at the registers. */
614 char *err = strerror (errno);
615 char *msg = alloca (strlen (err) + 128);
616 sprintf (msg, "reading register %d: %s", regno, err);
617 error (msg);
618 goto error_exit;
619 }
620 }
621 error_exit:;
622 }
623
624 /* Fetch all registers, or just one, from the child process. */
625
626 void
627 fetch_inferior_registers (int regno)
628 {
629 if (regno == -1 || regno == 0)
630 for (regno = 0; regno < NUM_REGS - NUM_FREGS; regno++)
631 fetch_register (regno);
632 else
633 fetch_register (regno);
634 }
635
636 /* Store our register values back into the inferior.
637 If REGNO is -1, do this for all registers.
638 Otherwise, REGNO specifies which register (so we can save time). */
639
640 void
641 store_inferior_registers (int regno)
642 {
643 CORE_ADDR regaddr;
644 int i;
645 unsigned int offset = U_REGS_OFFSET;
646
647 if (regno >= 0)
648 {
649 #if 0
650 if (CANNOT_STORE_REGISTER (regno))
651 return;
652 #endif
653 regaddr = register_addr (regno, offset);
654 errno = 0;
655 #if 0
656 if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
657 {
658 scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
659 ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
660 scratch, 0);
661 if (errno != 0)
662 {
663 /* Error, even if attached. Failing to write these two
664 registers is pretty serious. */
665 sprintf (buf, "writing register number %d", regno);
666 perror_with_name (buf);
667 }
668 }
669 else
670 #endif
671 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
672 {
673 errno = 0;
674 ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
675 *(int *) &registers[REGISTER_BYTE (regno) + i]);
676 if (errno != 0)
677 {
678 /* Warning, not error, in case we are attached; sometimes the
679 kernel doesn't let us at the registers. */
680 char *err = strerror (errno);
681 char *msg = alloca (strlen (err) + 128);
682 sprintf (msg, "writing register %d: %s",
683 regno, err);
684 error (msg);
685 return;
686 }
687 regaddr += sizeof (int);
688 }
689 }
690 else
691 for (regno = 0; regno < NUM_REGS - NUM_FREGS; regno++)
692 store_inferior_registers (regno);
693 }
694
695 /* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
696 in the NEW_SUN_PTRACE case.
697 It ought to be straightforward. But it appears that writing did
698 not write the data that I specified. I cannot understand where
699 it got the data that it actually did write. */
700
701 /* Copy LEN bytes from inferior's memory starting at MEMADDR
702 to debugger memory starting at MYADDR. */
703
704 void
705 read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
706 {
707 register int i;
708 /* Round starting address down to longword boundary. */
709 register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
710 /* Round ending address up; get number of longwords that makes. */
711 register int count
712 = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
713 / sizeof (PTRACE_XFER_TYPE);
714 /* Allocate buffer of that many longwords. */
715 register PTRACE_XFER_TYPE *buffer
716 = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
717
718 /* Read all the longwords */
719 for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
720 {
721 buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
722 }
723
724 /* Copy appropriate bytes out of the buffer. */
725 memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), len);
726 }
727
728 /* Copy LEN bytes of data from debugger memory at MYADDR
729 to inferior's memory at MEMADDR.
730 On failure (cannot write the inferior)
731 returns the value of errno. */
732
733 int
734 write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
735 {
736 register int i;
737 /* Round starting address down to longword boundary. */
738 register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
739 /* Round ending address up; get number of longwords that makes. */
740 register int count
741 = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) / sizeof (PTRACE_XFER_TYPE);
742 /* Allocate buffer of that many longwords. */
743 register PTRACE_XFER_TYPE *buffer = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
744 extern int errno;
745
746 /* Fill start and end extra bytes of buffer with existing memory data. */
747
748 buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
749
750 if (count > 1)
751 {
752 buffer[count - 1]
753 = ptrace (PTRACE_PEEKTEXT, inferior_pid,
754 addr + (count - 1) * sizeof (PTRACE_XFER_TYPE), 0);
755 }
756
757 /* Copy data to be written over corresponding part of buffer */
758
759 memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), myaddr, len);
760
761 /* Write the entire buffer. */
762
763 for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
764 {
765 errno = 0;
766 ptrace (PTRACE_POKETEXT, inferior_pid, addr, buffer[i]);
767 if (errno)
768 return errno;
769 }
770
771 return 0;
772 }
773 \f
774 void
775 initialize_low (void)
776 {
777 initialize_arch ();
778 }