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