blob: 32f8d098f3439adc9462788ce9f3e394d744e1b1 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046#ifdef SUNOS4
47#include <machine/reg.h>
48#include <a.out.h>
49#include <link.h>
50#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000051
Wichert Akkerman43a74822000-06-27 17:33:32 +000052#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Wichert Akkerman36915a11999-07-13 15:45:02 +000053#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000054#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000055
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000056#if defined(LINUX) && defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000057# include <asm/ptrace_offsets.h>
58# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000059#endif
60
Wichert Akkerman36915a11999-07-13 15:45:02 +000061#ifdef HAVE_SYS_REG_H
62#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
66#include <linux/ptrace.h>
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000067#endif
68
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
70#include <sys/utsname.h>
71#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
72
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000073#if defined(LINUX) && defined(SPARC)
74
75#include <asm/reg.h>
76
77#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000078
79#include <linux/unistd.h>
80
81#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
82 type5,arg5,syscall) \
83type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
84{ \
85 long __res; \
86\
87__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
88 "or %%g0, %2, %%o1\n\t" \
89 "or %%g0, %3, %%o2\n\t" \
90 "or %%g0, %4, %%o3\n\t" \
91 "or %%g0, %5, %%o4\n\t" \
92 "or %%g0, %6, %%g1\n\t" \
93 "t 0x10\n\t" \
94 "bcc 1f\n\t" \
95 "or %%g0, %%o0, %0\n\t" \
96 "sub %%g0, %%o0, %0\n\t" \
97 "1:\n\t" \
98 : "=r" (__res) \
99 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
100 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
101 "i" (__NR_##syscall) \
102 : "g1", "o0", "o1", "o2", "o3", "o4"); \
103if (__res>=0) \
104 return (type) __res; \
105errno = -__res; \
106return -1; \
107}
108
109static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
110
111#define _ptrace
112
113#endif
114
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000115#endif
116
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117/* macros */
118#ifndef MAX
119#define MAX(a,b) (((a) > (b)) ? (a) : (b))
120#endif
121#ifndef MIN
122#define MIN(a,b) (((a) < (b)) ? (a) : (b))
123#endif
124
125void
126tv_tv(tv, a, b)
127struct timeval *tv;
128int a;
129int b;
130{
131 tv->tv_sec = a;
132 tv->tv_usec = b;
133}
134
135int
136tv_nz(a)
137struct timeval *a;
138{
139 return a->tv_sec || a->tv_usec;
140}
141
142int
143tv_cmp(a, b)
144struct timeval *a, *b;
145{
146 if (a->tv_sec < b->tv_sec
147 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
148 return -1;
149 if (a->tv_sec > b->tv_sec
150 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
151 return 1;
152 return 0;
153}
154
155double
156tv_float(tv)
157struct timeval *tv;
158{
159 return tv->tv_sec + tv->tv_usec/1000000.0;
160}
161
162void
163tv_add(tv, a, b)
164struct timeval *tv, *a, *b;
165{
166 tv->tv_sec = a->tv_sec + b->tv_sec;
167 tv->tv_usec = a->tv_usec + b->tv_usec;
168 if (tv->tv_usec > 1000000) {
169 tv->tv_sec++;
170 tv->tv_usec -= 1000000;
171 }
172}
173
174void
175tv_sub(tv, a, b)
176struct timeval *tv, *a, *b;
177{
178 tv->tv_sec = a->tv_sec - b->tv_sec;
179 tv->tv_usec = a->tv_usec - b->tv_usec;
180 if (((long) tv->tv_usec) < 0) {
181 tv->tv_sec--;
182 tv->tv_usec += 1000000;
183 }
184}
185
186void
187tv_div(tv, a, n)
188struct timeval *tv, *a;
189int n;
190{
191 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
192 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
193 tv->tv_usec %= 1000000;
194}
195
196void
197tv_mul(tv, a, n)
198struct timeval *tv, *a;
199int n;
200{
201 tv->tv_usec = a->tv_usec * n;
202 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
203 tv->tv_usec %= 1000000;
204}
205
206char *
207xlookup(xlat, val)
208struct xlat *xlat;
209int val;
210{
211 for (; xlat->str != NULL; xlat++)
212 if (xlat->val == val)
213 return xlat->str;
214 return NULL;
215}
216
217/*
218 * Print entry in struct xlat table, if there.
219 */
220void
221printxval(xlat, val, dflt)
222struct xlat *xlat;
223int val;
224char *dflt;
225{
226 char *str = xlookup(xlat, val);
227
228 if (str)
229 tprintf("%s", str);
230 else
231 tprintf("%#x /* %s */", val, dflt);
232}
233
234/*
235 * Interpret `xlat' as an array of flags
236 * print the entries whose bits are on in `flags'
237 * return # of flags printed.
238 */
239int
240addflags(xlat, flags)
241struct xlat *xlat;
242int flags;
243{
244 int n;
245
246 for (n = 0; xlat->str; xlat++) {
247 if (xlat->val && (flags & xlat->val) == xlat->val) {
248 tprintf("|%s", xlat->str);
249 flags &= ~xlat->val;
250 n++;
251 }
252 }
253 if (flags) {
254 tprintf("|%#x", flags);
255 n++;
256 }
257 return n;
258}
259
260int
261printflags(xlat, flags)
262struct xlat *xlat;
263int flags;
264{
265 int n;
266 char *sep;
267
268 if (flags == 0 && xlat->val == 0) {
269 tprintf("%s", xlat->str);
270 return 1;
271 }
272
273 sep = "";
274 for (n = 0; xlat->str; xlat++) {
275 if (xlat->val && (flags & xlat->val) == xlat->val) {
276 tprintf("%s%s", sep, xlat->str);
277 flags &= ~xlat->val;
278 sep = "|";
279 n++;
280 }
281 }
282 if (flags) {
283 tprintf("%s%#x", sep, flags);
284 n++;
285 }
286 return n;
287}
288
289void
290printnum(tcp, addr, fmt)
291struct tcb *tcp;
292long addr;
293char *fmt;
294{
Roland McGratheb285352003-01-14 09:59:00 +0000295 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000296
297 if (!addr) {
298 tprintf("NULL");
299 return;
300 }
301 if (umove(tcp, addr, &num) < 0) {
302 tprintf("%#lx", addr);
303 return;
304 }
305 tprintf("[");
306 tprintf(fmt, num);
307 tprintf("]");
308}
309
310static char path[MAXPATHLEN + 1];
311
312void
313string_quote(str)
314char *str;
315{
316 char buf[2 * MAXPATHLEN + 1];
317 char *s;
318
319 if (!strpbrk(str, "\"\'\\")) {
320 tprintf("\"%s\"", str);
321 return;
322 }
323 for (s = buf; *str; str++) {
324 switch (*str) {
325 case '\"': case '\'': case '\\':
326 *s++ = '\\'; *s++ = *str; break;
327 default:
328 *s++ = *str; break;
329 }
330 }
331 *s = '\0';
332 tprintf("\"%s\"", buf);
333}
334
335void
336printpath(tcp, addr)
337struct tcb *tcp;
338long addr;
339{
340 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
341 tprintf("%#lx", addr);
342 else
343 string_quote(path);
344 return;
345}
346
347void
348printpathn(tcp, addr, n)
349struct tcb *tcp;
350long addr;
351int n;
352{
353 if (umovestr(tcp, addr, n, path) < 0)
354 tprintf("%#lx", addr);
355 else {
356 path[n] = '\0';
357 string_quote(path);
358 }
359}
360
361void
362printstr(tcp, addr, len)
363struct tcb *tcp;
364long addr;
365int len;
366{
367 static unsigned char *str = NULL;
368 static char *outstr;
369 int i, n, c, usehex;
370 char *s, *outend;
371
372 if (!addr) {
373 tprintf("NULL");
374 return;
375 }
376 if (!str) {
377 if ((str = malloc(max_strlen)) == NULL
378 || (outstr = malloc(2*max_strlen)) == NULL) {
379 fprintf(stderr, "printstr: no memory\n");
380 tprintf("%#lx", addr);
381 return;
382 }
383 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000384 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385 if (len < 0) {
386 n = max_strlen;
387 if (umovestr(tcp, addr, n, (char *) str) < 0) {
388 tprintf("%#lx", addr);
389 return;
390 }
391 }
392 else {
393 n = MIN(len, max_strlen);
394 if (umoven(tcp, addr, n, (char *) str) < 0) {
395 tprintf("%#lx", addr);
396 return;
397 }
398 }
399
400 usehex = 0;
401 if (xflag > 1)
402 usehex = 1;
403 else if (xflag) {
404 for (i = 0; i < n; i++) {
405 c = str[i];
406 if (len < 0 && c == '\0')
407 break;
408 if (!isprint(c) && !isspace(c)) {
409 usehex = 1;
410 break;
411 }
412 }
413 }
414
415 s = outstr;
416 *s++ = '\"';
417
418 if (usehex) {
419 for (i = 0; i < n; i++) {
420 c = str[i];
421 if (len < 0 && c == '\0')
422 break;
423 sprintf(s, "\\x%02x", c);
424 s += 4;
425 if (s > outend)
426 break;
427 }
428 }
429 else {
430 for (i = 0; i < n; i++) {
431 c = str[i];
432 if (len < 0 && c == '\0')
433 break;
434 switch (c) {
435 case '\"': case '\'': case '\\':
436 *s++ = '\\'; *s++ = c; break;
437 case '\f':
438 *s++ = '\\'; *s++ = 'f'; break;
439 case '\n':
440 *s++ = '\\'; *s++ = 'n'; break;
441 case '\r':
442 *s++ = '\\'; *s++ = 'r'; break;
443 case '\t':
444 *s++ = '\\'; *s++ = 't'; break;
445 case '\v':
446 *s++ = '\\'; *s++ = 'v'; break;
447 default:
448 if (isprint(c))
449 *s++ = c;
450 else if (i < n - 1 && isdigit(str[i + 1])) {
451 sprintf(s, "\\%03o", c);
452 s += 4;
453 }
454 else {
455 sprintf(s, "\\%o", c);
456 s += strlen(s);
457 }
458 break;
459 }
460 if (s > outend)
461 break;
462 }
463 }
464
465 *s++ = '\"';
466 if (i < len || (len < 0 && (i == n || s > outend))) {
467 *s++ = '.'; *s++ = '.'; *s++ = '.';
468 }
469 *s = '\0';
470 tprintf("%s", outstr);
471}
472
John Hughes1d08dcf2001-07-10 13:48:44 +0000473#if HAVE_SYS_UIO_H
474void
475dumpiov(tcp, len, addr)
476struct tcb * tcp;
477int len;
478long addr;
479{
480 struct iovec *iov;
481 int i;
482
Roland McGrath1e85cf92002-12-16 20:40:54 +0000483
John Hughes1d08dcf2001-07-10 13:48:44 +0000484 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
485 fprintf(stderr, "dump: No memory");
486 return;
487 }
488 if (umoven(tcp, addr,
489 len * sizeof *iov, (char *) iov) >= 0) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000490
John Hughes1d08dcf2001-07-10 13:48:44 +0000491 for (i = 0; i < len; i++) {
492 /* include the buffer number to make it easy to
493 * match up the trace with the source */
494 tprintf(" * %lu bytes in buffer %d\n",
495 (unsigned long)iov[i].iov_len, i);
496 dumpstr(tcp, (long) iov[i].iov_base,
497 iov[i].iov_len);
498 }
499 }
500 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000501
John Hughes1d08dcf2001-07-10 13:48:44 +0000502}
503#endif
504
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505void
506dumpstr(tcp, addr, len)
507struct tcb *tcp;
508long addr;
509int len;
510{
511 static int strsize = -1;
512 static unsigned char *str;
513 static char outstr[80];
514 char *s;
515 int i, j;
516
517 if (strsize < len) {
518 if (str)
519 free(str);
520 if ((str = malloc(len)) == NULL) {
521 fprintf(stderr, "dump: no memory\n");
522 return;
523 }
524 strsize = len;
525 }
526
527 if (umoven(tcp, addr, len, (char *) str) < 0)
528 return;
529
530 for (i = 0; i < len; i += 16) {
531 s = outstr;
532 sprintf(s, " | %05x ", i);
533 s += 9;
534 for (j = 0; j < 16; j++) {
535 if (j == 8)
536 *s++ = ' ';
537 if (i + j < len) {
538 sprintf(s, " %02x", str[i + j]);
539 s += 3;
540 }
541 else {
542 *s++ = ' '; *s++ = ' '; *s++ = ' ';
543 }
544 }
545 *s++ = ' '; *s++ = ' ';
546 for (j = 0; j < 16; j++) {
547 if (j == 8)
548 *s++ = ' ';
549 if (i + j < len) {
550 if (isprint(str[i + j]))
551 *s++ = str[i + j];
552 else
553 *s++ = '.';
554 }
555 else
556 *s++ = ' ';
557 }
558 tprintf("%s |\n", outstr);
559 }
560}
561
562#define PAGMASK (~(PAGSIZ - 1))
563/*
564 * move `len' bytes of data from process `pid'
565 * at address `addr' to our space at `laddr'
566 */
567int
568umoven(tcp, addr, len, laddr)
569struct tcb *tcp;
570long addr;
571int len;
572char *laddr;
573{
574
575#ifdef LINUX
576 int pid = tcp->pid;
577 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000578 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000579 union {
580 long val;
581 char x[sizeof(long)];
582 } u;
583
584 if (addr & (sizeof(long) - 1)) {
585 /* addr not a multiple of sizeof(long) */
586 n = addr - (addr & -sizeof(long)); /* residue */
587 addr &= -sizeof(long); /* residue */
588 errno = 0;
589 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
590 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000591 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000592 /* Ran into 'end of memory' - stupid "printpath" */
593 return 0;
594 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000595 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596 perror("ptrace: umoven");
597 return -1;
598 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000599 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000600 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
601 addr += sizeof(long), laddr += m, len -= m;
602 }
603 while (len) {
604 errno = 0;
605 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
606 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000607 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000608 /* Ran into 'end of memory' - stupid "printpath" */
609 return 0;
610 }
611 perror("ptrace: umoven");
612 return -1;
613 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000614 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000615 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
616 addr += sizeof(long), laddr += m, len -= m;
617 }
618#endif /* LINUX */
619
620#ifdef SUNOS4
621 int pid = tcp->pid;
622#if 0
623 int n, m;
624 union {
625 long val;
626 char x[sizeof(long)];
627 } u;
628
629 if (addr & (sizeof(long) - 1)) {
630 /* addr not a multiple of sizeof(long) */
631 n = addr - (addr & -sizeof(long)); /* residue */
632 addr &= -sizeof(long); /* residue */
633 errno = 0;
634 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
635 if (errno) {
636 perror("umoven");
637 return -1;
638 }
639 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
640 addr += sizeof(long), laddr += m, len -= m;
641 }
642 while (len) {
643 errno = 0;
644 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
645 if (errno) {
646 perror("umoven");
647 return -1;
648 }
649 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
650 addr += sizeof(long), laddr += m, len -= m;
651 }
652#else /* !oldway */
653 int n;
654
655 while (len) {
656 n = MIN(len, PAGSIZ);
657 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
658 if (ptrace(PTRACE_READDATA, pid,
659 (char *) addr, len, laddr) < 0) {
660 perror("umoven: ptrace(PTRACE_READDATA, ...)");
661 abort();
662 return -1;
663 }
664 len -= n;
665 addr += n;
666 laddr += n;
667 }
668#endif /* !oldway */
669#endif /* SUNOS4 */
670
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000671#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000672#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000673 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000674#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000675 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000677 lseek(fd, addr, SEEK_SET);
678 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000679 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000680#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000681
682 return 0;
683}
684
685/*
686 * like `umove' but make the additional effort of looking
687 * for a terminating zero byte.
688 */
689int
690umovestr(tcp, addr, len, laddr)
691struct tcb *tcp;
692long addr;
693int len;
694char *laddr;
695{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000696#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000697#ifdef HAVE_MP_PROCFS
698 int fd = tcp->pfd_as;
699#else
700 int fd = tcp->pfd;
701#endif
702 /* Some systems (e.g. FreeBSD) can be upset if we read off the
703 end of valid memory, avoid this by trying to read up
704 to page boundaries. But we don't know what a page is (and
705 getpagesize(2) (if it exists) doesn't necessarily return
706 hardware page size). Assume all pages >= 1024 (a-historical
707 I know) */
708
709 int page = 1024; /* How to find this? */
710 int move = page - (addr & (page - 1));
711 int left = len;
712
713 lseek(fd, addr, SEEK_SET);
714
715 while (left) {
716 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000717 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000718 return left != len ? 0 : -1;
719 if (memchr (laddr, 0, move)) break;
720 left -= move;
721 laddr += move;
722 addr += move;
723 move = page;
724 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000725#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000726 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000727 int pid = tcp->pid;
728 int i, n, m;
729 union {
730 long val;
731 char x[sizeof(long)];
732 } u;
733
734 if (addr & (sizeof(long) - 1)) {
735 /* addr not a multiple of sizeof(long) */
736 n = addr - (addr & -sizeof(long)); /* residue */
737 addr &= -sizeof(long); /* residue */
738 errno = 0;
739 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
740 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000741 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000742 /* Ran into 'end of memory' - stupid "printpath" */
743 return 0;
744 }
745 perror("umovestr");
746 return -1;
747 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000748 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000749 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
750 while (n & (sizeof(long) - 1))
751 if (u.x[n++] == '\0')
752 return 0;
753 addr += sizeof(long), laddr += m, len -= m;
754 }
755 while (len) {
756 errno = 0;
757 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
758 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000759 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 /* Ran into 'end of memory' - stupid "printpath" */
761 return 0;
762 }
763 perror("umovestr");
764 return -1;
765 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000766 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
768 for (i = 0; i < sizeof(long); i++)
769 if (u.x[i] == '\0')
770 return 0;
771
772 addr += sizeof(long), laddr += m, len -= m;
773 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000774#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000775 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776}
777
778#ifdef LINUX
779#ifndef SPARC
780#define PTRACE_WRITETEXT 101
781#define PTRACE_WRITEDATA 102
782#endif /* !SPARC */
783#endif /* LINUX */
784
785#ifdef SUNOS4
786
787static int
788uload(cmd, pid, addr, len, laddr)
789int cmd;
790int pid;
791long addr;
792int len;
793char *laddr;
794{
795#if 0
796 int n;
797
798 while (len) {
799 n = MIN(len, PAGSIZ);
800 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
801 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
802 perror("uload: ptrace(PTRACE_WRITE, ...)");
803 return -1;
804 }
805 len -= n;
806 addr += n;
807 laddr += n;
808 }
809#else
810 int peek, poke;
811 int n, m;
812 union {
813 long val;
814 char x[sizeof(long)];
815 } u;
816
817 if (cmd == PTRACE_WRITETEXT) {
818 peek = PTRACE_PEEKTEXT;
819 poke = PTRACE_POKETEXT;
820 }
821 else {
822 peek = PTRACE_PEEKDATA;
823 poke = PTRACE_POKEDATA;
824 }
825 if (addr & (sizeof(long) - 1)) {
826 /* addr not a multiple of sizeof(long) */
827 n = addr - (addr & -sizeof(long)); /* residue */
828 addr &= -sizeof(long);
829 errno = 0;
830 u.val = ptrace(peek, pid, (char *) addr, 0);
831 if (errno) {
832 perror("uload: POKE");
833 return -1;
834 }
835 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
836 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
837 perror("uload: POKE");
838 return -1;
839 }
840 addr += sizeof(long), laddr += m, len -= m;
841 }
842 while (len) {
843 if (len < sizeof(long))
844 u.val = ptrace(peek, pid, (char *) addr, 0);
845 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
846 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
847 perror("uload: POKE");
848 return -1;
849 }
850 addr += sizeof(long), laddr += m, len -= m;
851 }
852#endif
853 return 0;
854}
855
856int
857tload(pid, addr, len, laddr)
858int pid;
859int addr, len;
860char *laddr;
861{
862 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
863}
864
865int
866dload(pid, addr, len, laddr)
867int pid;
868int addr;
869int len;
870char *laddr;
871{
872 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
873}
874
875#endif /* SUNOS4 */
876
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000877#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878
879int
880upeek(pid, off, res)
881int pid;
882long off;
883long *res;
884{
885 long val;
886
887#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
888 {
889 static int is_sun4m = -1;
890 struct utsname name;
891
892 /* Round up the usual suspects. */
893 if (is_sun4m == -1) {
894 if (uname(&name) < 0) {
895 perror("upeek: uname?");
896 exit(1);
897 }
898 is_sun4m = strcmp(name.machine, "sun4m") == 0;
899 if (is_sun4m) {
900 extern struct xlat struct_user_offsets[];
901 struct xlat *x;
902
903 for (x = struct_user_offsets; x->str; x++)
904 x->val += 1024;
905 }
906 }
907 if (is_sun4m)
908 off += 1024;
909 }
910#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
911 errno = 0;
912 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
913 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000914 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000915 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000916 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000917 return -1;
918 }
919 *res = val;
920 return 0;
921}
922
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000923#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000924
925long
926getpc(tcp)
927struct tcb *tcp;
928{
929
930#ifdef LINUX
931 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000932#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
934 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000935#elif defined(X86_64)
936 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
937 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000938#elif defined(IA64)
939 if (upeek(tcp->pid, PT_B0, &pc) < 0)
940 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000941#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 if (upeek(tcp->pid, 4*15, &pc) < 0)
943 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000944#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000945 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000946 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000947#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
949 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000950#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 if (upeek(tcp->pid, REG_PC, &pc) < 0)
952 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000953#elif defined(MIPS)
954 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
955 return -1;
956#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000957 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
959 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000960 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000961#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000962 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +0000963 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000964#elif defined(HPPA)
965 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
966 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000967#elif defined(SH)
968 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
969 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +0000970#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 return pc;
972#endif /* LINUX */
973
974#ifdef SUNOS4
975 /*
976 * Return current program counter for `pid'
977 * Assumes PC is never 0xffffffff
978 */
979 struct regs regs;
980
981 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
982 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
983 return -1;
984 }
985 return regs.r_pc;
986#endif /* SUNOS4 */
987
988#ifdef SVR4
989 /* XXX */
990 return 0;
991#endif /* SVR4 */
992
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000993#ifdef FREEBSD
994 struct reg regs;
995 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
996 return regs.r_eip;
997#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998}
999
1000void
1001printcall(tcp)
1002struct tcb *tcp;
1003{
1004
1005#ifdef LINUX
1006#ifdef I386
1007 long eip;
1008
1009 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1010 tprintf("[????????] ");
1011 return;
1012 }
1013 tprintf("[%08lx] ", eip);
Michal Ludvig0e035502002-09-23 15:41:01 +00001014#elif defined(X86_64)
1015 long rip;
1016
1017 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1018 tprintf("[????????] ");
1019 return;
1020 }
1021 tprintf("[%16lx] ", rip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001022#elif defined(IA62)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001023 long ip;
1024
1025 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1026 tprintf("[????????] ");
1027 return;
1028 }
1029 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001030#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 long pc;
1032
Roland McGratheb285352003-01-14 09:59:00 +00001033 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 tprintf ("[????????] ");
1035 return;
1036 }
1037 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001038#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 long pc;
1040
1041 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1042 tprintf ("[????????] ");
1043 return;
1044 }
1045 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001046#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 long pc;
1048
1049 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1050 tprintf ("[????????] ");
1051 return;
1052 }
1053 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001054#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001055 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1057 tprintf("[????????] ");
1058 return;
1059 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001060 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001061#elif defined(HPPA)
1062 long pc;
1063
1064 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1065 tprintf ("[????????] ");
1066 return;
1067 }
1068 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001069#elif defined(MIPS)
1070 long pc;
1071
1072 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1073 tprintf ("[????????] ");
1074 return;
1075 }
1076 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001077#elif defined(SH)
1078 long pc;
1079
1080 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1081 tprintf ("[????????] ");
1082 return;
1083 }
1084 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001085#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001086#endif /* LINUX */
1087
1088#ifdef SUNOS4
1089 struct regs regs;
1090
1091 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1092 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1093 tprintf("[????????] ");
1094 return;
1095 }
1096 tprintf("[%08x] ", regs.r_o7);
1097#endif /* SUNOS4 */
1098
1099#ifdef SVR4
1100 /* XXX */
1101 tprintf("[????????] ");
1102#endif
1103
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001104#ifdef FREEBSD
1105 struct reg regs;
1106 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1107 tprintf("[%08x] ", regs.r_eip);
1108#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109}
1110
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001111#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112
Roland McGrathd81f1d92003-01-09 06:53:34 +00001113#if defined LINUX
1114
1115#include <sys/syscall.h>
1116#ifndef CLONE_PTRACE
1117# define CLONE_PTRACE 0x00002000
1118#endif
1119
1120#ifdef IA64
1121
1122typedef unsigned long *arg_setup_state;
1123
1124static int
1125arg_setup(struct tcb *tcp, arg_setup_state *state)
1126{
1127 unsigned long *bsp, cfm, sof, sol;
1128
1129 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1130 return -1;
1131 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1132 return -1;
1133
1134 sof = (cfm >> 0) & 0x7f;
1135 sol = (cfm >> 7) & 0x7f;
1136 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1137
1138 *state = bsp;
1139 return 0;
1140}
1141
1142# define arg_finish_change(tcp, state) 0
1143
1144#ifdef SYS_fork
1145static int
1146get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1147{
1148 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
1149 sizeof(long), (void *) valp);
1150}
1151
1152static int
1153get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1154{
1155 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
1156 sizeof(long), (void *) valp);
1157}
1158#endif
1159
1160static int
1161set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1162{
1163 unsigned long *ap;
1164 ap = ia64_rse_skip_regs(*state, 0);
1165 errno = 0;
1166 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1167 return errno ? -1 : 0;
1168}
1169
1170static int
1171set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1172{
1173 unsigned long *ap;
1174 ap = ia64_rse_skip_regs(*state, 1);
1175 errno = 0;
1176 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1177 return errno ? -1 : 0;
1178}
1179
1180#elif defined (SPARC)
1181
1182typedef struct regs arg_setup_state;
1183
1184# define arg_setup(tcp, state) \
1185 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1186# define arg_finish_change(tcp, state) \
1187 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1188
1189# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1190# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1191# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1192# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001193# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001194
1195#else
1196
1197# if defined S390 || defined S390X
1198# define arg0_offset PT_ORIGGPR2
1199# define arg1_offset PT_GPR2
Roland McGrathe1df47f2003-01-14 09:46:15 +00001200# define restore_arg0(tcp, state, val) 0
1201# define restore_arg1(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202# elif defined (ALPHA) || defined (MIPS)
1203# define arg0_offset REG_A0
1204# define arg1_offset (REG_A0+1)
1205# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001206# define arg0_offset (sizeof(unsigned long)*PT_R3)
1207# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001208# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001209# elif defined (HPPA)
1210# define arg0_offset PT_GR26
1211# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001212# elif defined (X86_64)
1213# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1214# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001215# else
1216# define arg0_offset 0
1217# define arg1_offset 4
Roland McGrathe1df47f2003-01-14 09:46:15 +00001218# if defined SH || defined ARM
1219# define restore_arg0(tcp, state, val) 0
1220# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001221# endif
1222
1223typedef int arg_setup_state;
1224
1225# define arg_setup(tcp, state) (0)
1226# define arg_finish_change(tcp, state) 0
1227# define get_arg0(tcp, cookie, valp) \
1228 (upeek ((tcp)->pid, arg0_offset, (valp)))
1229# define get_arg1(tcp, cookie, valp) \
1230 (upeek ((tcp)->pid, arg1_offset, (valp)))
1231
1232static int
1233set_arg0 (struct tcb *tcp, void *cookie, long val)
1234{
1235 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1236}
1237
1238static int
1239set_arg1 (struct tcb *tcp, void *cookie, long val)
1240{
1241 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1242}
1243
1244#endif
1245
Roland McGrathe1df47f2003-01-14 09:46:15 +00001246#ifndef restore_arg0
1247# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1248#endif
1249#ifndef restore_arg1
1250# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1251#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001252
1253int
1254setbpt(tcp)
1255struct tcb *tcp;
1256{
1257 extern int change_syscall(struct tcb *, int);
1258 arg_setup_state state;
1259
1260 if (tcp->flags & TCB_BPTSET) {
1261 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1262 return -1;
1263 }
1264
1265 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001266#ifdef SYS_vfork
1267 case SYS_vfork:
1268#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001269#ifdef SYS_fork
1270 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001271#endif
1272#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001273 if (arg_setup (tcp, &state) < 0
1274 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1275 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1276 || change_syscall(tcp, SYS_clone) < 0
1277 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1278 || set_arg1 (tcp, &state, 0) < 0
1279 || arg_finish_change (tcp, &state) < 0)
1280 return -1;
1281 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1282 tcp->u_arg[1] = 0;
1283 tcp->flags |= TCB_BPTSET;
1284 return 0;
1285#endif
1286
1287 case SYS_clone:
1288#ifdef SYS_clone2
1289 case SYS_clone2:
1290#endif
1291 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1292 && (arg_setup (tcp, &state) < 0
1293 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1294 || arg_finish_change (tcp, &state) < 0))
1295 return -1;
1296 tcp->flags |= TCB_BPTSET;
1297 tcp->inst[0] = tcp->u_arg[0];
1298 tcp->inst[1] = tcp->u_arg[1];
1299 return 0;
1300
1301 default:
1302 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1303 tcp->scno, tcp->pid);
1304 break;
1305 }
1306
1307 return -1;
1308}
1309
1310int
1311clearbpt(tcp)
1312struct tcb *tcp;
1313{
1314 arg_setup_state state;
1315 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001316 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1317 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001318 || arg_finish_change (tcp, &state))
1319 return -1;
1320 tcp->flags &= ~TCB_BPTSET;
1321 return 0;
1322}
1323
1324#else
1325
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001326int
1327setbpt(tcp)
1328struct tcb *tcp;
1329{
1330
1331#ifdef LINUX
1332#ifdef SPARC
1333 /* We simply use the SunOS breakpoint code. */
1334
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001335 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336#define LOOPA 0x30800000 /* ba,a 0 */
1337
1338 if (tcp->flags & TCB_BPTSET) {
1339 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1340 return -1;
1341 }
1342 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1343 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1344 return -1;
1345 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001346 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001347 errno = 0;
1348 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1349 if(errno) {
1350 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1351 return -1;
1352 }
1353
1354 /*
1355 * XXX - BRUTAL MODE ON
1356 * We cannot set a real BPT in the child, since it will not be
1357 * traced at the moment it will reach the trap and would probably
1358 * die with a core dump.
1359 * Thus, we are force our way in by taking out two instructions
1360 * and insert an eternal loop instead, in expectance of the SIGSTOP
1361 * generated by out PTRACE_ATTACH.
1362 * Of cause, if we evaporate ourselves in the middle of all this...
1363 */
1364 errno = 0;
1365 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1366 if(errno) {
1367 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1368 return -1;
1369 }
1370 tcp->flags |= TCB_BPTSET;
1371
1372#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001373#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001374 if (ia32) {
1375# define LOOP 0x0000feeb
1376 if (tcp->flags & TCB_BPTSET) {
1377 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1378 tcp->pid);
1379 return -1;
1380 }
1381 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1382 return -1;
1383 if (debug)
1384 fprintf(stderr, "[%d] setting bpt at %lx\n",
1385 tcp->pid, tcp->baddr);
1386 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1387 (char *) tcp->baddr, 0);
1388 if (errno) {
1389 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1390 return -1;
1391 }
1392 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1393 if (errno) {
1394 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1395 return -1;
1396 }
1397 tcp->flags |= TCB_BPTSET;
1398 } else {
1399 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001400 * Our strategy here is to replace the bundle that
1401 * contained the clone() syscall with a bundle of the
1402 * form:
1403 *
1404 * { 1: br 1b; br 1b; br 1b }
1405 *
1406 * This ensures that the newly forked child will loop
1407 * endlessly until we've got a chance to attach to it.
1408 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001409# define LOOP0 0x0000100000000017
1410# define LOOP1 0x4000000000200000
1411 unsigned long addr, ipsr;
1412 pid_t pid;
1413
1414 pid = tcp->pid;
1415 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1416 return -1;
1417 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1418 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001419 /* store "ri" in low two bits */
1420 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001421
1422 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001423 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1424 0);
1425 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1426 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001427 if (errno) {
1428 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1429 return -1;
1430 }
1431
1432 errno = 0;
1433 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1434 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1435 if (errno) {
1436 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1437 return -1;
1438 }
1439 tcp->flags |= TCB_BPTSET;
1440 }
1441#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442
Michal Ludvig0e035502002-09-23 15:41:01 +00001443#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444#define LOOP 0x0000feeb
1445#elif defined (M68K)
1446#define LOOP 0x60fe0000
1447#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001448#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001450#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001452#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001453#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001454#define LOOP 0x1000ffff
1455#elif defined(S390)
1456#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001457#elif defined(S390X)
1458#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001459#elif defined(HPPA)
1460#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001461#elif defined(SH)
1462#ifdef __LITTLE_ENDIAN__
1463#define LOOP 0x0000affe
1464#else
1465#define LOOP 0xfeaf0000
1466#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001467#else
1468#error unknown architecture
1469#endif
1470
1471 if (tcp->flags & TCB_BPTSET) {
1472 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1473 return -1;
1474 }
1475#if defined (I386)
1476 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1477 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001478#elif defined (X86_64)
1479 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1480 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481#elif defined (M68K)
1482 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1483 return -1;
1484#elif defined (ALPHA)
1485 return -1;
1486#elif defined (ARM)
1487 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001488#elif defined (MIPS)
1489 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001490#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001491 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001493#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001494 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1495 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001496#elif defined(HPPA)
1497 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1498 return -1;
1499 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001500#elif defined(SH)
1501 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1502 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503#else
1504#error unknown architecture
1505#endif
1506 if (debug)
1507 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1508 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1509 if (errno) {
1510 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1511 return -1;
1512 }
1513 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1514 if (errno) {
1515 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1516 return -1;
1517 }
1518 tcp->flags |= TCB_BPTSET;
1519
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001520#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001521#endif /* SPARC */
1522#endif /* LINUX */
1523
1524#ifdef SUNOS4
1525#ifdef SPARC /* This code is slightly sparc specific */
1526
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001527 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528#define BPT 0x91d02001 /* ta 1 */
1529#define LOOP 0x10800000 /* ba 0 */
1530#define LOOPA 0x30800000 /* ba,a 0 */
1531#define NOP 0x01000000
1532#if LOOPA
1533 static int loopdeloop[1] = {LOOPA};
1534#else
1535 static int loopdeloop[2] = {LOOP, NOP};
1536#endif
1537
1538 if (tcp->flags & TCB_BPTSET) {
1539 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1540 return -1;
1541 }
1542 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1543 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1544 return -1;
1545 }
1546 tcp->baddr = regs.r_o7 + 8;
1547 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1548 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1549 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1550 return -1;
1551 }
1552
1553 /*
1554 * XXX - BRUTAL MODE ON
1555 * We cannot set a real BPT in the child, since it will not be
1556 * traced at the moment it will reach the trap and would probably
1557 * die with a core dump.
1558 * Thus, we are force our way in by taking out two instructions
1559 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1560 * generated by out PTRACE_ATTACH.
1561 * Of cause, if we evaporate ourselves in the middle of all this...
1562 */
1563 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1564 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1565 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1566 return -1;
1567 }
1568 tcp->flags |= TCB_BPTSET;
1569
1570#endif /* SPARC */
1571#endif /* SUNOS4 */
1572
1573 return 0;
1574}
1575
1576int
1577clearbpt(tcp)
1578struct tcb *tcp;
1579{
1580
1581#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001582#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001584#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001586#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001588#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001590#elif defined(HPPA)
1591 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001592#elif defined(SH)
1593 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001594#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001595
1596#ifdef SPARC
1597 /* Again, we borrow the SunOS breakpoint code. */
1598 if (!(tcp->flags & TCB_BPTSET)) {
1599 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1600 return -1;
1601 }
1602 errno = 0;
1603 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1604 if(errno) {
1605 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1606 return -1;
1607 }
1608 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001609#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001610 if (ia32) {
1611 unsigned long addr;
1612
1613 if (debug)
1614 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1615 if (!(tcp->flags & TCB_BPTSET)) {
1616 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1617 return -1;
1618 }
1619 errno = 0;
1620 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1621 if (errno) {
1622 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1623 return -1;
1624 }
1625 tcp->flags &= ~TCB_BPTSET;
1626
1627 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1628 return -1;
1629 if (addr != tcp->baddr) {
1630 /* The breakpoint has not been reached yet. */
1631 if (debug)
1632 fprintf(stderr,
1633 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1634 addr, tcp->baddr);
1635 return 0;
1636 }
1637 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001638 unsigned long addr, ipsr;
1639 pid_t pid;
1640
1641 pid = tcp->pid;
1642
1643 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1644 return -1;
1645 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1646 return -1;
1647
1648 /* restore original bundle: */
1649 errno = 0;
1650 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1651 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1652 if (errno) {
1653 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1654 return -1;
1655 }
1656
1657 /* restore original "ri" in ipsr: */
1658 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1659 errno = 0;
1660 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1661 if (errno) {
1662 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1663 return -1;
1664 }
1665
1666 tcp->flags &= ~TCB_BPTSET;
1667
1668 if (addr != (tcp->baddr & ~0x3)) {
1669 /* the breakpoint has not been reached yet. */
1670 if (debug)
1671 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1672 addr, tcp->baddr);
1673 return 0;
1674 }
1675 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001676#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677
1678 if (debug)
1679 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1680 if (!(tcp->flags & TCB_BPTSET)) {
1681 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1682 return -1;
1683 }
1684 errno = 0;
1685 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1686 if (errno) {
1687 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1688 return -1;
1689 }
1690 tcp->flags &= ~TCB_BPTSET;
1691
1692#ifdef I386
1693 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1694 return -1;
1695 if (eip != tcp->baddr) {
1696 /* The breakpoint has not been reached yet. */
1697 if (debug)
1698 fprintf(stderr,
1699 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1700 eip, tcp->baddr);
1701 return 0;
1702 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001703#elif defined(X86_64)
1704 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1705 return -1;
1706 if (eip != tcp->baddr) {
1707 /* The breakpoint has not been reached yet. */
1708 if (debug)
1709 fprintf(stderr,
1710 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1711 eip, tcp->baddr);
1712 return 0;
1713 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001714#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001715 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716 return -1;
1717 if (pc != tcp->baddr) {
1718 /* The breakpoint has not been reached yet. */
1719 if (debug)
1720 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1721 pc, tcp->baddr);
1722 return 0;
1723 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001724#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1726 return -1;
1727 if (pc != tcp->baddr) {
1728 /* The breakpoint has not been reached yet. */
1729 if (debug)
1730 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1731 pc, tcp->baddr);
1732 return 0;
1733 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001734#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1736 return -1;
1737 if (pc != tcp->baddr) {
1738 /* The breakpoint has not been reached yet. */
1739 if (debug)
1740 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1741 pc, tcp->baddr);
1742 return 0;
1743 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001744#elif defined(HPPA)
1745 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1746 return -1;
1747 iaoq &= ~0x03;
1748 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1749 /* The breakpoint has not been reached yet. */
1750 if (debug)
1751 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1752 iaoq, tcp->baddr);
1753 return 0;
1754 }
1755 iaoq = tcp->baddr | 3;
1756 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1757 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1758 * has no significant effect.
1759 */
1760 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1761 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001762#elif defined(SH)
1763 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1764 return -1;
1765 if (pc != tcp->baddr) {
1766 /* The breakpoint has not been reached yet. */
1767 if (debug)
1768 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1769 pc, tcp->baddr);
1770 return 0;
1771 }
1772
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001773#endif /* arch */
1774#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775#endif /* LINUX */
1776
1777#ifdef SUNOS4
1778#ifdef SPARC
1779
1780#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001781 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782#endif
1783
1784 if (!(tcp->flags & TCB_BPTSET)) {
1785 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1786 return -1;
1787 }
1788 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1789 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1790 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1791 return -1;
1792 }
1793 tcp->flags &= ~TCB_BPTSET;
1794
1795#if !LOOPA
1796 /*
1797 * Since we don't have a single instruction breakpoint, we may have
1798 * to adjust the program counter after removing the our `breakpoint'.
1799 */
1800 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1801 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1802 return -1;
1803 }
1804 if ((regs.r_pc < tcp->baddr) ||
1805 (regs.r_pc > tcp->baddr + 4)) {
1806 /* The breakpoint has not been reached yet */
1807 if (debug)
1808 fprintf(stderr,
1809 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1810 regs.r_pc, tcp->parent->baddr);
1811 return 0;
1812 }
1813 if (regs.r_pc != tcp->baddr)
1814 if (debug)
1815 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1816 regs.r_pc, tcp->baddr);
1817
1818 regs.r_pc = tcp->baddr;
1819 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1820 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1821 return -1;
1822 }
1823#endif /* LOOPA */
1824#endif /* SPARC */
1825#endif /* SUNOS4 */
1826
1827 return 0;
1828}
1829
Roland McGrathd81f1d92003-01-09 06:53:34 +00001830#endif
1831
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001832#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833
1834#ifdef SUNOS4
1835
1836static int
1837getex(pid, hdr)
1838int pid;
1839struct exec *hdr;
1840{
1841 int n;
1842
1843 for (n = 0; n < sizeof *hdr; n += 4) {
1844 long res;
1845 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1846 return -1;
1847 memcpy(((char *) hdr) + n, &res, 4);
1848 }
1849 if (debug) {
1850 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1851 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1852 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1853 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1854 }
1855 return 0;
1856}
1857
1858int
1859fixvfork(tcp)
1860struct tcb *tcp;
1861{
1862 int pid = tcp->pid;
1863 /*
1864 * Change `vfork' in a freshly exec'ed dynamically linked
1865 * executable's (internal) symbol table to plain old `fork'
1866 */
1867
1868 struct exec hdr;
1869 struct link_dynamic dyn;
1870 struct link_dynamic_2 ld;
1871 char *strtab, *cp;
1872
1873 if (getex(pid, &hdr) < 0)
1874 return -1;
1875 if (!hdr.a_dynamic)
1876 return -1;
1877
1878 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1879 fprintf(stderr, "Cannot read DYNAMIC\n");
1880 return -1;
1881 }
1882 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1883 fprintf(stderr, "Cannot read link_dynamic_2\n");
1884 return -1;
1885 }
1886 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1887 fprintf(stderr, "fixvfork: out of memory\n");
1888 return -1;
1889 }
1890 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1891 (int)ld.ld_symb_size, strtab) < 0)
1892 goto err;
1893
1894#if 0
1895 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1896 fprintf(stderr, "[symbol: %s]\n", cp);
1897 cp += strlen(cp)+1;
1898 }
1899 return 0;
1900#endif
1901 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1902 if (strcmp(cp, "_vfork") == 0) {
1903 if (debug)
1904 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1905 strcpy(cp, "_fork");
1906 break;
1907 }
1908 cp += strlen(cp)+1;
1909 }
1910 if (cp < strtab + ld.ld_symb_size)
1911 /*
1912 * Write entire symbol table back to avoid
1913 * memory alignment bugs in ptrace
1914 */
1915 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1916 (int)ld.ld_symb_size, strtab) < 0)
1917 goto err;
1918
1919 free(strtab);
1920 return 0;
1921
1922err:
1923 free(strtab);
1924 return -1;
1925}
1926
1927#endif /* SUNOS4 */