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