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