blob: c2ec5fe6029ce1bdee1189256f1dd09ff0d2ba32 [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
Roland McGrath4db26242003-01-30 20:15:19 +000075# define fpq kernel_fpq
76# define fq kernel_fq
77# define fpu kernel_fpu
78# include <asm/reg.h>
79# undef fpq
80# undef fq
81# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
83#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
85#include <linux/unistd.h>
86
87#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
88 type5,arg5,syscall) \
89type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
90{ \
91 long __res; \
92\
93__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
94 "or %%g0, %2, %%o1\n\t" \
95 "or %%g0, %3, %%o2\n\t" \
96 "or %%g0, %4, %%o3\n\t" \
97 "or %%g0, %5, %%o4\n\t" \
98 "or %%g0, %6, %%g1\n\t" \
99 "t 0x10\n\t" \
100 "bcc 1f\n\t" \
101 "or %%g0, %%o0, %0\n\t" \
102 "sub %%g0, %%o0, %0\n\t" \
103 "1:\n\t" \
104 : "=r" (__res) \
105 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
106 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
107 "i" (__NR_##syscall) \
108 : "g1", "o0", "o1", "o2", "o3", "o4"); \
109if (__res>=0) \
110 return (type) __res; \
111errno = -__res; \
112return -1; \
113}
114
115static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
116
117#define _ptrace
118
119#endif
120
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000121#endif
122
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123/* macros */
124#ifndef MAX
125#define MAX(a,b) (((a) > (b)) ? (a) : (b))
126#endif
127#ifndef MIN
128#define MIN(a,b) (((a) < (b)) ? (a) : (b))
129#endif
130
131void
132tv_tv(tv, a, b)
133struct timeval *tv;
134int a;
135int b;
136{
137 tv->tv_sec = a;
138 tv->tv_usec = b;
139}
140
141int
142tv_nz(a)
143struct timeval *a;
144{
145 return a->tv_sec || a->tv_usec;
146}
147
148int
149tv_cmp(a, b)
150struct timeval *a, *b;
151{
152 if (a->tv_sec < b->tv_sec
153 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
154 return -1;
155 if (a->tv_sec > b->tv_sec
156 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
157 return 1;
158 return 0;
159}
160
161double
162tv_float(tv)
163struct timeval *tv;
164{
165 return tv->tv_sec + tv->tv_usec/1000000.0;
166}
167
168void
169tv_add(tv, a, b)
170struct timeval *tv, *a, *b;
171{
172 tv->tv_sec = a->tv_sec + b->tv_sec;
173 tv->tv_usec = a->tv_usec + b->tv_usec;
174 if (tv->tv_usec > 1000000) {
175 tv->tv_sec++;
176 tv->tv_usec -= 1000000;
177 }
178}
179
180void
181tv_sub(tv, a, b)
182struct timeval *tv, *a, *b;
183{
184 tv->tv_sec = a->tv_sec - b->tv_sec;
185 tv->tv_usec = a->tv_usec - b->tv_usec;
186 if (((long) tv->tv_usec) < 0) {
187 tv->tv_sec--;
188 tv->tv_usec += 1000000;
189 }
190}
191
192void
193tv_div(tv, a, n)
194struct timeval *tv, *a;
195int n;
196{
197 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
198 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
199 tv->tv_usec %= 1000000;
200}
201
202void
203tv_mul(tv, a, n)
204struct timeval *tv, *a;
205int n;
206{
207 tv->tv_usec = a->tv_usec * n;
208 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
209 tv->tv_usec %= 1000000;
210}
211
212char *
213xlookup(xlat, val)
214struct xlat *xlat;
215int val;
216{
217 for (; xlat->str != NULL; xlat++)
218 if (xlat->val == val)
219 return xlat->str;
220 return NULL;
221}
222
223/*
224 * Print entry in struct xlat table, if there.
225 */
226void
227printxval(xlat, val, dflt)
228struct xlat *xlat;
229int val;
230char *dflt;
231{
232 char *str = xlookup(xlat, val);
233
234 if (str)
235 tprintf("%s", str);
236 else
237 tprintf("%#x /* %s */", val, dflt);
238}
239
240/*
241 * Interpret `xlat' as an array of flags
242 * print the entries whose bits are on in `flags'
243 * return # of flags printed.
244 */
245int
246addflags(xlat, flags)
247struct xlat *xlat;
248int flags;
249{
250 int n;
251
252 for (n = 0; xlat->str; xlat++) {
253 if (xlat->val && (flags & xlat->val) == xlat->val) {
254 tprintf("|%s", xlat->str);
255 flags &= ~xlat->val;
256 n++;
257 }
258 }
259 if (flags) {
260 tprintf("|%#x", flags);
261 n++;
262 }
263 return n;
264}
265
266int
267printflags(xlat, flags)
268struct xlat *xlat;
269int flags;
270{
271 int n;
272 char *sep;
273
274 if (flags == 0 && xlat->val == 0) {
275 tprintf("%s", xlat->str);
276 return 1;
277 }
278
279 sep = "";
280 for (n = 0; xlat->str; xlat++) {
281 if (xlat->val && (flags & xlat->val) == xlat->val) {
282 tprintf("%s%s", sep, xlat->str);
283 flags &= ~xlat->val;
284 sep = "|";
285 n++;
286 }
287 }
288 if (flags) {
289 tprintf("%s%#x", sep, flags);
290 n++;
291 }
292 return n;
293}
294
295void
296printnum(tcp, addr, fmt)
297struct tcb *tcp;
298long addr;
299char *fmt;
300{
Roland McGratheb285352003-01-14 09:59:00 +0000301 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302
303 if (!addr) {
304 tprintf("NULL");
305 return;
306 }
307 if (umove(tcp, addr, &num) < 0) {
308 tprintf("%#lx", addr);
309 return;
310 }
311 tprintf("[");
312 tprintf(fmt, num);
313 tprintf("]");
314}
315
316static char path[MAXPATHLEN + 1];
317
318void
319string_quote(str)
320char *str;
321{
322 char buf[2 * MAXPATHLEN + 1];
323 char *s;
324
325 if (!strpbrk(str, "\"\'\\")) {
326 tprintf("\"%s\"", str);
327 return;
328 }
329 for (s = buf; *str; str++) {
330 switch (*str) {
331 case '\"': case '\'': case '\\':
332 *s++ = '\\'; *s++ = *str; break;
333 default:
334 *s++ = *str; break;
335 }
336 }
337 *s = '\0';
338 tprintf("\"%s\"", buf);
339}
340
341void
342printpath(tcp, addr)
343struct tcb *tcp;
344long addr;
345{
346 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
347 tprintf("%#lx", addr);
348 else
349 string_quote(path);
350 return;
351}
352
353void
354printpathn(tcp, addr, n)
355struct tcb *tcp;
356long addr;
357int n;
358{
359 if (umovestr(tcp, addr, n, path) < 0)
360 tprintf("%#lx", addr);
361 else {
362 path[n] = '\0';
363 string_quote(path);
364 }
365}
366
367void
368printstr(tcp, addr, len)
369struct tcb *tcp;
370long addr;
371int len;
372{
373 static unsigned char *str = NULL;
374 static char *outstr;
375 int i, n, c, usehex;
376 char *s, *outend;
377
378 if (!addr) {
379 tprintf("NULL");
380 return;
381 }
382 if (!str) {
383 if ((str = malloc(max_strlen)) == NULL
384 || (outstr = malloc(2*max_strlen)) == NULL) {
385 fprintf(stderr, "printstr: no memory\n");
386 tprintf("%#lx", addr);
387 return;
388 }
389 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000390 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391 if (len < 0) {
392 n = max_strlen;
393 if (umovestr(tcp, addr, n, (char *) str) < 0) {
394 tprintf("%#lx", addr);
395 return;
396 }
397 }
398 else {
399 n = MIN(len, max_strlen);
400 if (umoven(tcp, addr, n, (char *) str) < 0) {
401 tprintf("%#lx", addr);
402 return;
403 }
404 }
405
406 usehex = 0;
407 if (xflag > 1)
408 usehex = 1;
409 else if (xflag) {
410 for (i = 0; i < n; i++) {
411 c = str[i];
412 if (len < 0 && c == '\0')
413 break;
414 if (!isprint(c) && !isspace(c)) {
415 usehex = 1;
416 break;
417 }
418 }
419 }
420
421 s = outstr;
422 *s++ = '\"';
423
424 if (usehex) {
425 for (i = 0; i < n; i++) {
426 c = str[i];
427 if (len < 0 && c == '\0')
428 break;
429 sprintf(s, "\\x%02x", c);
430 s += 4;
431 if (s > outend)
432 break;
433 }
434 }
435 else {
436 for (i = 0; i < n; i++) {
437 c = str[i];
438 if (len < 0 && c == '\0')
439 break;
440 switch (c) {
441 case '\"': case '\'': case '\\':
442 *s++ = '\\'; *s++ = c; break;
443 case '\f':
444 *s++ = '\\'; *s++ = 'f'; break;
445 case '\n':
446 *s++ = '\\'; *s++ = 'n'; break;
447 case '\r':
448 *s++ = '\\'; *s++ = 'r'; break;
449 case '\t':
450 *s++ = '\\'; *s++ = 't'; break;
451 case '\v':
452 *s++ = '\\'; *s++ = 'v'; break;
453 default:
454 if (isprint(c))
455 *s++ = c;
456 else if (i < n - 1 && isdigit(str[i + 1])) {
457 sprintf(s, "\\%03o", c);
458 s += 4;
459 }
460 else {
461 sprintf(s, "\\%o", c);
462 s += strlen(s);
463 }
464 break;
465 }
466 if (s > outend)
467 break;
468 }
469 }
470
471 *s++ = '\"';
472 if (i < len || (len < 0 && (i == n || s > outend))) {
473 *s++ = '.'; *s++ = '.'; *s++ = '.';
474 }
475 *s = '\0';
476 tprintf("%s", outstr);
477}
478
John Hughes1d08dcf2001-07-10 13:48:44 +0000479#if HAVE_SYS_UIO_H
480void
481dumpiov(tcp, len, addr)
482struct tcb * tcp;
483int len;
484long addr;
485{
486 struct iovec *iov;
487 int i;
488
Roland McGrath1e85cf92002-12-16 20:40:54 +0000489
John Hughes1d08dcf2001-07-10 13:48:44 +0000490 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
491 fprintf(stderr, "dump: No memory");
492 return;
493 }
494 if (umoven(tcp, addr,
495 len * sizeof *iov, (char *) iov) >= 0) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000496
John Hughes1d08dcf2001-07-10 13:48:44 +0000497 for (i = 0; i < len; i++) {
498 /* include the buffer number to make it easy to
499 * match up the trace with the source */
500 tprintf(" * %lu bytes in buffer %d\n",
501 (unsigned long)iov[i].iov_len, i);
502 dumpstr(tcp, (long) iov[i].iov_base,
503 iov[i].iov_len);
504 }
505 }
506 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000507
John Hughes1d08dcf2001-07-10 13:48:44 +0000508}
509#endif
510
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511void
512dumpstr(tcp, addr, len)
513struct tcb *tcp;
514long addr;
515int len;
516{
517 static int strsize = -1;
518 static unsigned char *str;
519 static char outstr[80];
520 char *s;
521 int i, j;
522
523 if (strsize < len) {
524 if (str)
525 free(str);
526 if ((str = malloc(len)) == NULL) {
527 fprintf(stderr, "dump: no memory\n");
528 return;
529 }
530 strsize = len;
531 }
532
533 if (umoven(tcp, addr, len, (char *) str) < 0)
534 return;
535
536 for (i = 0; i < len; i += 16) {
537 s = outstr;
538 sprintf(s, " | %05x ", i);
539 s += 9;
540 for (j = 0; j < 16; j++) {
541 if (j == 8)
542 *s++ = ' ';
543 if (i + j < len) {
544 sprintf(s, " %02x", str[i + j]);
545 s += 3;
546 }
547 else {
548 *s++ = ' '; *s++ = ' '; *s++ = ' ';
549 }
550 }
551 *s++ = ' '; *s++ = ' ';
552 for (j = 0; j < 16; j++) {
553 if (j == 8)
554 *s++ = ' ';
555 if (i + j < len) {
556 if (isprint(str[i + j]))
557 *s++ = str[i + j];
558 else
559 *s++ = '.';
560 }
561 else
562 *s++ = ' ';
563 }
564 tprintf("%s |\n", outstr);
565 }
566}
567
568#define PAGMASK (~(PAGSIZ - 1))
569/*
570 * move `len' bytes of data from process `pid'
571 * at address `addr' to our space at `laddr'
572 */
573int
574umoven(tcp, addr, len, laddr)
575struct tcb *tcp;
576long addr;
577int len;
578char *laddr;
579{
580
581#ifdef LINUX
582 int pid = tcp->pid;
583 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000584 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000585 union {
586 long val;
587 char x[sizeof(long)];
588 } u;
589
590 if (addr & (sizeof(long) - 1)) {
591 /* addr not a multiple of sizeof(long) */
592 n = addr - (addr & -sizeof(long)); /* residue */
593 addr &= -sizeof(long); /* residue */
594 errno = 0;
595 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
596 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000597 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598 /* Ran into 'end of memory' - stupid "printpath" */
599 return 0;
600 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000601 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602 perror("ptrace: umoven");
603 return -1;
604 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000605 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
607 addr += sizeof(long), laddr += m, len -= m;
608 }
609 while (len) {
610 errno = 0;
611 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
612 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000613 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614 /* Ran into 'end of memory' - stupid "printpath" */
615 return 0;
616 }
Roland McGrath4db26242003-01-30 20:15:19 +0000617 if (addr != 0)
618 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000619 return -1;
620 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000621 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000622 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
623 addr += sizeof(long), laddr += m, len -= m;
624 }
625#endif /* LINUX */
626
627#ifdef SUNOS4
628 int pid = tcp->pid;
629#if 0
630 int n, m;
631 union {
632 long val;
633 char x[sizeof(long)];
634 } u;
635
636 if (addr & (sizeof(long) - 1)) {
637 /* addr not a multiple of sizeof(long) */
638 n = addr - (addr & -sizeof(long)); /* residue */
639 addr &= -sizeof(long); /* residue */
640 errno = 0;
641 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
642 if (errno) {
643 perror("umoven");
644 return -1;
645 }
646 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
647 addr += sizeof(long), laddr += m, len -= m;
648 }
649 while (len) {
650 errno = 0;
651 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
652 if (errno) {
653 perror("umoven");
654 return -1;
655 }
656 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
657 addr += sizeof(long), laddr += m, len -= m;
658 }
659#else /* !oldway */
660 int n;
661
662 while (len) {
663 n = MIN(len, PAGSIZ);
664 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
665 if (ptrace(PTRACE_READDATA, pid,
666 (char *) addr, len, laddr) < 0) {
667 perror("umoven: ptrace(PTRACE_READDATA, ...)");
668 abort();
669 return -1;
670 }
671 len -= n;
672 addr += n;
673 laddr += n;
674 }
675#endif /* !oldway */
676#endif /* SUNOS4 */
677
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000678#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000679#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000680 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000681#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000682 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000684 lseek(fd, addr, SEEK_SET);
685 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000686 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000687#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000688
689 return 0;
690}
691
692/*
693 * like `umove' but make the additional effort of looking
694 * for a terminating zero byte.
695 */
696int
697umovestr(tcp, addr, len, laddr)
698struct tcb *tcp;
699long addr;
700int len;
701char *laddr;
702{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000703#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000704#ifdef HAVE_MP_PROCFS
705 int fd = tcp->pfd_as;
706#else
707 int fd = tcp->pfd;
708#endif
709 /* Some systems (e.g. FreeBSD) can be upset if we read off the
710 end of valid memory, avoid this by trying to read up
711 to page boundaries. But we don't know what a page is (and
712 getpagesize(2) (if it exists) doesn't necessarily return
713 hardware page size). Assume all pages >= 1024 (a-historical
714 I know) */
715
716 int page = 1024; /* How to find this? */
717 int move = page - (addr & (page - 1));
718 int left = len;
719
720 lseek(fd, addr, SEEK_SET);
721
722 while (left) {
723 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000724 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000725 return left != len ? 0 : -1;
726 if (memchr (laddr, 0, move)) break;
727 left -= move;
728 laddr += move;
729 addr += move;
730 move = page;
731 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000732#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000733 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000734 int pid = tcp->pid;
735 int i, n, m;
736 union {
737 long val;
738 char x[sizeof(long)];
739 } u;
740
741 if (addr & (sizeof(long) - 1)) {
742 /* addr not a multiple of sizeof(long) */
743 n = addr - (addr & -sizeof(long)); /* residue */
744 addr &= -sizeof(long); /* residue */
745 errno = 0;
746 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
747 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000748 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000749 /* Ran into 'end of memory' - stupid "printpath" */
750 return 0;
751 }
752 perror("umovestr");
753 return -1;
754 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000755 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
757 while (n & (sizeof(long) - 1))
758 if (u.x[n++] == '\0')
759 return 0;
760 addr += sizeof(long), laddr += m, len -= m;
761 }
762 while (len) {
763 errno = 0;
764 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
765 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000766 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 /* Ran into 'end of memory' - stupid "printpath" */
768 return 0;
769 }
770 perror("umovestr");
771 return -1;
772 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000773 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000774 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
775 for (i = 0; i < sizeof(long); i++)
776 if (u.x[i] == '\0')
777 return 0;
778
779 addr += sizeof(long), laddr += m, len -= m;
780 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000781#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000782 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783}
784
785#ifdef LINUX
786#ifndef SPARC
787#define PTRACE_WRITETEXT 101
788#define PTRACE_WRITEDATA 102
789#endif /* !SPARC */
790#endif /* LINUX */
791
792#ifdef SUNOS4
793
794static int
795uload(cmd, pid, addr, len, laddr)
796int cmd;
797int pid;
798long addr;
799int len;
800char *laddr;
801{
802#if 0
803 int n;
804
805 while (len) {
806 n = MIN(len, PAGSIZ);
807 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
808 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
809 perror("uload: ptrace(PTRACE_WRITE, ...)");
810 return -1;
811 }
812 len -= n;
813 addr += n;
814 laddr += n;
815 }
816#else
817 int peek, poke;
818 int n, m;
819 union {
820 long val;
821 char x[sizeof(long)];
822 } u;
823
824 if (cmd == PTRACE_WRITETEXT) {
825 peek = PTRACE_PEEKTEXT;
826 poke = PTRACE_POKETEXT;
827 }
828 else {
829 peek = PTRACE_PEEKDATA;
830 poke = PTRACE_POKEDATA;
831 }
832 if (addr & (sizeof(long) - 1)) {
833 /* addr not a multiple of sizeof(long) */
834 n = addr - (addr & -sizeof(long)); /* residue */
835 addr &= -sizeof(long);
836 errno = 0;
837 u.val = ptrace(peek, pid, (char *) addr, 0);
838 if (errno) {
839 perror("uload: POKE");
840 return -1;
841 }
842 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
843 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
844 perror("uload: POKE");
845 return -1;
846 }
847 addr += sizeof(long), laddr += m, len -= m;
848 }
849 while (len) {
850 if (len < sizeof(long))
851 u.val = ptrace(peek, pid, (char *) addr, 0);
852 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
853 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
854 perror("uload: POKE");
855 return -1;
856 }
857 addr += sizeof(long), laddr += m, len -= m;
858 }
859#endif
860 return 0;
861}
862
863int
864tload(pid, addr, len, laddr)
865int pid;
866int addr, len;
867char *laddr;
868{
869 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
870}
871
872int
873dload(pid, addr, len, laddr)
874int pid;
875int addr;
876int len;
877char *laddr;
878{
879 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
880}
881
882#endif /* SUNOS4 */
883
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000884#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885
886int
887upeek(pid, off, res)
888int pid;
889long off;
890long *res;
891{
892 long val;
893
894#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
895 {
896 static int is_sun4m = -1;
897 struct utsname name;
898
899 /* Round up the usual suspects. */
900 if (is_sun4m == -1) {
901 if (uname(&name) < 0) {
902 perror("upeek: uname?");
903 exit(1);
904 }
905 is_sun4m = strcmp(name.machine, "sun4m") == 0;
906 if (is_sun4m) {
907 extern struct xlat struct_user_offsets[];
908 struct xlat *x;
909
910 for (x = struct_user_offsets; x->str; x++)
911 x->val += 1024;
912 }
913 }
914 if (is_sun4m)
915 off += 1024;
916 }
917#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
918 errno = 0;
919 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
920 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000921 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000922 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000923 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000924 return -1;
925 }
926 *res = val;
927 return 0;
928}
929
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000930#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931
932long
933getpc(tcp)
934struct tcb *tcp;
935{
936
937#ifdef LINUX
938 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000939#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
941 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000942#elif defined(X86_64)
943 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
944 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000945#elif defined(IA64)
946 if (upeek(tcp->pid, PT_B0, &pc) < 0)
947 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000948#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949 if (upeek(tcp->pid, 4*15, &pc) < 0)
950 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000951#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000952 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000954#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
956 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000957#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 if (upeek(tcp->pid, REG_PC, &pc) < 0)
959 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000960#elif defined(MIPS)
961 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
962 return -1;
963#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000964 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
966 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000967 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000968#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000969 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +0000970 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000971#elif defined(HPPA)
972 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
973 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000974#elif defined(SH)
975 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
976 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +0000977#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +0000978 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
979 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +0000980#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000981 return pc;
982#endif /* LINUX */
983
984#ifdef SUNOS4
985 /*
986 * Return current program counter for `pid'
987 * Assumes PC is never 0xffffffff
988 */
989 struct regs regs;
990
991 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
992 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
993 return -1;
994 }
995 return regs.r_pc;
996#endif /* SUNOS4 */
997
998#ifdef SVR4
999 /* XXX */
1000 return 0;
1001#endif /* SVR4 */
1002
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001003#ifdef FREEBSD
1004 struct reg regs;
1005 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1006 return regs.r_eip;
1007#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008}
1009
1010void
1011printcall(tcp)
1012struct tcb *tcp;
1013{
1014
1015#ifdef LINUX
1016#ifdef I386
1017 long eip;
1018
1019 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1020 tprintf("[????????] ");
1021 return;
1022 }
1023 tprintf("[%08lx] ", eip);
Michal Ludvig0e035502002-09-23 15:41:01 +00001024#elif defined(X86_64)
1025 long rip;
1026
1027 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1028 tprintf("[????????] ");
1029 return;
1030 }
1031 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001032#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001033 long ip;
1034
1035 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1036 tprintf("[????????] ");
1037 return;
1038 }
1039 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001040#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 long pc;
1042
Roland McGratheb285352003-01-14 09:59:00 +00001043 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001044 tprintf ("[????????] ");
1045 return;
1046 }
1047 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001048#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001049 long pc;
1050
1051 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1052 tprintf ("[????????] ");
1053 return;
1054 }
1055 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001056#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 long pc;
1058
1059 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1060 tprintf ("[????????] ");
1061 return;
1062 }
1063 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001064#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001065 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1067 tprintf("[????????] ");
1068 return;
1069 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001070 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001071#elif defined(HPPA)
1072 long pc;
1073
1074 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1075 tprintf ("[????????] ");
1076 return;
1077 }
1078 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001079#elif defined(MIPS)
1080 long pc;
1081
1082 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1083 tprintf ("[????????] ");
1084 return;
1085 }
1086 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001087#elif defined(SH)
1088 long pc;
1089
1090 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1091 tprintf ("[????????] ");
1092 return;
1093 }
1094 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001095#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001096 long pc;
1097
1098 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1099 tprintf ("[????????] ");
1100 return;
1101 }
1102 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001103#elif defined(ARM)
1104 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001105
Roland McGrathef388682003-06-03 23:28:59 +00001106 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1107 tprintf("[????????] ");
1108 return;
1109 }
1110 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001111#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112#endif /* LINUX */
1113
1114#ifdef SUNOS4
1115 struct regs regs;
1116
1117 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1118 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1119 tprintf("[????????] ");
1120 return;
1121 }
1122 tprintf("[%08x] ", regs.r_o7);
1123#endif /* SUNOS4 */
1124
1125#ifdef SVR4
1126 /* XXX */
1127 tprintf("[????????] ");
1128#endif
1129
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001130#ifdef FREEBSD
1131 struct reg regs;
1132 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1133 tprintf("[%08x] ", regs.r_eip);
1134#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135}
1136
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001137#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138
Roland McGrathd81f1d92003-01-09 06:53:34 +00001139#if defined LINUX
1140
1141#include <sys/syscall.h>
1142#ifndef CLONE_PTRACE
1143# define CLONE_PTRACE 0x00002000
1144#endif
1145
1146#ifdef IA64
1147
1148typedef unsigned long *arg_setup_state;
1149
1150static int
1151arg_setup(struct tcb *tcp, arg_setup_state *state)
1152{
1153 unsigned long *bsp, cfm, sof, sol;
1154
1155 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1156 return -1;
1157 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1158 return -1;
1159
1160 sof = (cfm >> 0) & 0x7f;
1161 sol = (cfm >> 7) & 0x7f;
1162 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1163
1164 *state = bsp;
1165 return 0;
1166}
1167
1168# define arg_finish_change(tcp, state) 0
1169
1170#ifdef SYS_fork
1171static int
1172get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1173{
1174 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
1175 sizeof(long), (void *) valp);
1176}
1177
1178static int
1179get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1180{
1181 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
1182 sizeof(long), (void *) valp);
1183}
1184#endif
1185
1186static int
1187set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1188{
1189 unsigned long *ap;
1190 ap = ia64_rse_skip_regs(*state, 0);
1191 errno = 0;
1192 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1193 return errno ? -1 : 0;
1194}
1195
1196static int
1197set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1198{
1199 unsigned long *ap;
1200 ap = ia64_rse_skip_regs(*state, 1);
1201 errno = 0;
1202 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1203 return errno ? -1 : 0;
1204}
1205
1206#elif defined (SPARC)
1207
1208typedef struct regs arg_setup_state;
1209
1210# define arg_setup(tcp, state) \
1211 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1212# define arg_finish_change(tcp, state) \
1213 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1214
1215# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1216# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1217# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1218# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001219# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001220
1221#else
1222
1223# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001224/* Note: this is only true for the `clone' system call, which handles
1225 arguments specially. We could as well say that its first two arguments
1226 are swapped relative to other architectures, but that would just be
1227 another #ifdef in the calls. */
1228# define arg0_offset PT_GPR3
1229# define arg1_offset PT_ORIGGPR2
1230# define restore_arg0(tcp, state, val) ((void) (state), 0)
1231# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001232# elif defined (ALPHA) || defined (MIPS)
1233# define arg0_offset REG_A0
1234# define arg1_offset (REG_A0+1)
1235# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001236# define arg0_offset (sizeof(unsigned long)*PT_R3)
1237# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001238# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001239# elif defined (HPPA)
1240# define arg0_offset PT_GR26
1241# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001242# elif defined (X86_64)
1243# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1244# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001245# elif defined (SH)
1246# define arg0_offset (4*(REG_REG0+4))
1247# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001248# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001249 /* ABI defines arg0 & 1 in r2 & r3 */
1250# define arg0_offset (REG_OFFSET+16)
1251# define arg1_offset (REG_OFFSET+24)
1252# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001253# else
1254# define arg0_offset 0
1255# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001256# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001257# define restore_arg0(tcp, state, val) 0
1258# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001259# endif
1260
1261typedef int arg_setup_state;
1262
1263# define arg_setup(tcp, state) (0)
1264# define arg_finish_change(tcp, state) 0
1265# define get_arg0(tcp, cookie, valp) \
1266 (upeek ((tcp)->pid, arg0_offset, (valp)))
1267# define get_arg1(tcp, cookie, valp) \
1268 (upeek ((tcp)->pid, arg1_offset, (valp)))
1269
1270static int
1271set_arg0 (struct tcb *tcp, void *cookie, long val)
1272{
1273 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1274}
1275
1276static int
1277set_arg1 (struct tcb *tcp, void *cookie, long val)
1278{
1279 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1280}
1281
1282#endif
1283
Roland McGrathe1df47f2003-01-14 09:46:15 +00001284#ifndef restore_arg0
1285# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1286#endif
1287#ifndef restore_arg1
1288# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1289#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001290
1291int
1292setbpt(tcp)
1293struct tcb *tcp;
1294{
1295 extern int change_syscall(struct tcb *, int);
1296 arg_setup_state state;
1297
1298 if (tcp->flags & TCB_BPTSET) {
1299 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1300 return -1;
1301 }
1302
1303 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001304#ifdef SYS_vfork
1305 case SYS_vfork:
1306#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001307#ifdef SYS_fork
1308 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001309#endif
1310#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001311 if (arg_setup (tcp, &state) < 0
1312 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1313 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1314 || change_syscall(tcp, SYS_clone) < 0
1315 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1316 || set_arg1 (tcp, &state, 0) < 0
1317 || arg_finish_change (tcp, &state) < 0)
1318 return -1;
1319 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1320 tcp->u_arg[1] = 0;
1321 tcp->flags |= TCB_BPTSET;
1322 return 0;
1323#endif
1324
1325 case SYS_clone:
1326#ifdef SYS_clone2
1327 case SYS_clone2:
1328#endif
1329 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1330 && (arg_setup (tcp, &state) < 0
1331 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1332 || arg_finish_change (tcp, &state) < 0))
1333 return -1;
1334 tcp->flags |= TCB_BPTSET;
1335 tcp->inst[0] = tcp->u_arg[0];
1336 tcp->inst[1] = tcp->u_arg[1];
1337 return 0;
1338
1339 default:
1340 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1341 tcp->scno, tcp->pid);
1342 break;
1343 }
1344
1345 return -1;
1346}
1347
1348int
1349clearbpt(tcp)
1350struct tcb *tcp;
1351{
1352 arg_setup_state state;
1353 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001354 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1355 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001356 || arg_finish_change (tcp, &state))
1357 return -1;
1358 tcp->flags &= ~TCB_BPTSET;
1359 return 0;
1360}
1361
1362#else
1363
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001364int
1365setbpt(tcp)
1366struct tcb *tcp;
1367{
1368
1369#ifdef LINUX
1370#ifdef SPARC
1371 /* We simply use the SunOS breakpoint code. */
1372
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001373 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374#define LOOPA 0x30800000 /* ba,a 0 */
1375
1376 if (tcp->flags & TCB_BPTSET) {
1377 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1378 return -1;
1379 }
1380 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1381 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1382 return -1;
1383 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001384 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385 errno = 0;
1386 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1387 if(errno) {
1388 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1389 return -1;
1390 }
1391
1392 /*
1393 * XXX - BRUTAL MODE ON
1394 * We cannot set a real BPT in the child, since it will not be
1395 * traced at the moment it will reach the trap and would probably
1396 * die with a core dump.
1397 * Thus, we are force our way in by taking out two instructions
1398 * and insert an eternal loop instead, in expectance of the SIGSTOP
1399 * generated by out PTRACE_ATTACH.
1400 * Of cause, if we evaporate ourselves in the middle of all this...
1401 */
1402 errno = 0;
1403 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1404 if(errno) {
1405 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1406 return -1;
1407 }
1408 tcp->flags |= TCB_BPTSET;
1409
1410#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001411#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001412 if (ia32) {
1413# define LOOP 0x0000feeb
1414 if (tcp->flags & TCB_BPTSET) {
1415 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1416 tcp->pid);
1417 return -1;
1418 }
1419 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1420 return -1;
1421 if (debug)
1422 fprintf(stderr, "[%d] setting bpt at %lx\n",
1423 tcp->pid, tcp->baddr);
1424 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1425 (char *) tcp->baddr, 0);
1426 if (errno) {
1427 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1428 return -1;
1429 }
1430 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1431 if (errno) {
1432 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1433 return -1;
1434 }
1435 tcp->flags |= TCB_BPTSET;
1436 } else {
1437 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001438 * Our strategy here is to replace the bundle that
1439 * contained the clone() syscall with a bundle of the
1440 * form:
1441 *
1442 * { 1: br 1b; br 1b; br 1b }
1443 *
1444 * This ensures that the newly forked child will loop
1445 * endlessly until we've got a chance to attach to it.
1446 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001447# define LOOP0 0x0000100000000017
1448# define LOOP1 0x4000000000200000
1449 unsigned long addr, ipsr;
1450 pid_t pid;
1451
1452 pid = tcp->pid;
1453 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1454 return -1;
1455 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1456 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001457 /* store "ri" in low two bits */
1458 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001459
1460 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001461 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1462 0);
1463 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1464 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001465 if (errno) {
1466 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1467 return -1;
1468 }
1469
1470 errno = 0;
1471 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1472 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1473 if (errno) {
1474 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1475 return -1;
1476 }
1477 tcp->flags |= TCB_BPTSET;
1478 }
1479#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480
Michal Ludvig0e035502002-09-23 15:41:01 +00001481#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482#define LOOP 0x0000feeb
1483#elif defined (M68K)
1484#define LOOP 0x60fe0000
1485#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001486#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001488#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001490#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001491#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001492#define LOOP 0x1000ffff
1493#elif defined(S390)
1494#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001495#elif defined(S390X)
1496#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001497#elif defined(HPPA)
1498#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001499#elif defined(SH)
1500#ifdef __LITTLE_ENDIAN__
1501#define LOOP 0x0000affe
1502#else
1503#define LOOP 0xfeaf0000
1504#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001505#else
1506#error unknown architecture
1507#endif
1508
1509 if (tcp->flags & TCB_BPTSET) {
1510 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1511 return -1;
1512 }
1513#if defined (I386)
1514 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1515 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001516#elif defined (X86_64)
1517 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1518 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519#elif defined (M68K)
1520 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1521 return -1;
1522#elif defined (ALPHA)
1523 return -1;
1524#elif defined (ARM)
1525 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001526#elif defined (MIPS)
1527 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001529 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001531#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001532 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1533 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001534#elif defined(HPPA)
1535 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1536 return -1;
1537 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001538#elif defined(SH)
1539 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1540 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541#else
1542#error unknown architecture
1543#endif
1544 if (debug)
1545 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1546 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1547 if (errno) {
1548 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1549 return -1;
1550 }
1551 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1552 if (errno) {
1553 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1554 return -1;
1555 }
1556 tcp->flags |= TCB_BPTSET;
1557
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001558#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001559#endif /* SPARC */
1560#endif /* LINUX */
1561
1562#ifdef SUNOS4
1563#ifdef SPARC /* This code is slightly sparc specific */
1564
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001565 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566#define BPT 0x91d02001 /* ta 1 */
1567#define LOOP 0x10800000 /* ba 0 */
1568#define LOOPA 0x30800000 /* ba,a 0 */
1569#define NOP 0x01000000
1570#if LOOPA
1571 static int loopdeloop[1] = {LOOPA};
1572#else
1573 static int loopdeloop[2] = {LOOP, NOP};
1574#endif
1575
1576 if (tcp->flags & TCB_BPTSET) {
1577 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1578 return -1;
1579 }
1580 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1581 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1582 return -1;
1583 }
1584 tcp->baddr = regs.r_o7 + 8;
1585 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1586 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1587 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1588 return -1;
1589 }
1590
1591 /*
1592 * XXX - BRUTAL MODE ON
1593 * We cannot set a real BPT in the child, since it will not be
1594 * traced at the moment it will reach the trap and would probably
1595 * die with a core dump.
1596 * Thus, we are force our way in by taking out two instructions
1597 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1598 * generated by out PTRACE_ATTACH.
1599 * Of cause, if we evaporate ourselves in the middle of all this...
1600 */
1601 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1602 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1603 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1604 return -1;
1605 }
1606 tcp->flags |= TCB_BPTSET;
1607
1608#endif /* SPARC */
1609#endif /* SUNOS4 */
1610
1611 return 0;
1612}
1613
1614int
1615clearbpt(tcp)
1616struct tcb *tcp;
1617{
1618
1619#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001620#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001622#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001624#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001626#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001628#elif defined(HPPA)
1629 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001630#elif defined(SH)
1631 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001632#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633
1634#ifdef SPARC
1635 /* Again, we borrow the SunOS breakpoint code. */
1636 if (!(tcp->flags & TCB_BPTSET)) {
1637 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1638 return -1;
1639 }
1640 errno = 0;
1641 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1642 if(errno) {
1643 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1644 return -1;
1645 }
1646 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001647#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001648 if (ia32) {
1649 unsigned long addr;
1650
1651 if (debug)
1652 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1653 if (!(tcp->flags & TCB_BPTSET)) {
1654 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1655 return -1;
1656 }
1657 errno = 0;
1658 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1659 if (errno) {
1660 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1661 return -1;
1662 }
1663 tcp->flags &= ~TCB_BPTSET;
1664
1665 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1666 return -1;
1667 if (addr != tcp->baddr) {
1668 /* The breakpoint has not been reached yet. */
1669 if (debug)
1670 fprintf(stderr,
1671 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1672 addr, tcp->baddr);
1673 return 0;
1674 }
1675 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001676 unsigned long addr, ipsr;
1677 pid_t pid;
1678
1679 pid = tcp->pid;
1680
1681 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1682 return -1;
1683 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1684 return -1;
1685
1686 /* restore original bundle: */
1687 errno = 0;
1688 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1689 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1690 if (errno) {
1691 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1692 return -1;
1693 }
1694
1695 /* restore original "ri" in ipsr: */
1696 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1697 errno = 0;
1698 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1699 if (errno) {
1700 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1701 return -1;
1702 }
1703
1704 tcp->flags &= ~TCB_BPTSET;
1705
1706 if (addr != (tcp->baddr & ~0x3)) {
1707 /* the breakpoint has not been reached yet. */
1708 if (debug)
1709 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1710 addr, tcp->baddr);
1711 return 0;
1712 }
1713 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001714#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715
1716 if (debug)
1717 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1718 if (!(tcp->flags & TCB_BPTSET)) {
1719 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1720 return -1;
1721 }
1722 errno = 0;
1723 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1724 if (errno) {
1725 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1726 return -1;
1727 }
1728 tcp->flags &= ~TCB_BPTSET;
1729
1730#ifdef I386
1731 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1732 return -1;
1733 if (eip != tcp->baddr) {
1734 /* The breakpoint has not been reached yet. */
1735 if (debug)
1736 fprintf(stderr,
1737 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1738 eip, tcp->baddr);
1739 return 0;
1740 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001741#elif defined(X86_64)
1742 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1743 return -1;
1744 if (eip != tcp->baddr) {
1745 /* The breakpoint has not been reached yet. */
1746 if (debug)
1747 fprintf(stderr,
1748 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1749 eip, tcp->baddr);
1750 return 0;
1751 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001752#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001753 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754 return -1;
1755 if (pc != tcp->baddr) {
1756 /* The breakpoint has not been reached yet. */
1757 if (debug)
1758 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1759 pc, tcp->baddr);
1760 return 0;
1761 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001762#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763 if (upeek(tcp->pid, 4*PT_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 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001772#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1774 return -1;
1775 if (pc != tcp->baddr) {
1776 /* The breakpoint has not been reached yet. */
1777 if (debug)
1778 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1779 pc, tcp->baddr);
1780 return 0;
1781 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001782#elif defined(HPPA)
1783 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1784 return -1;
1785 iaoq &= ~0x03;
1786 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1787 /* The breakpoint has not been reached yet. */
1788 if (debug)
1789 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1790 iaoq, tcp->baddr);
1791 return 0;
1792 }
1793 iaoq = tcp->baddr | 3;
1794 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1795 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1796 * has no significant effect.
1797 */
1798 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1799 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001800#elif defined(SH)
1801 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1802 return -1;
1803 if (pc != tcp->baddr) {
1804 /* The breakpoint has not been reached yet. */
1805 if (debug)
1806 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1807 pc, tcp->baddr);
1808 return 0;
1809 }
1810
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001811#endif /* arch */
1812#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813#endif /* LINUX */
1814
1815#ifdef SUNOS4
1816#ifdef SPARC
1817
1818#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001819 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001820#endif
1821
1822 if (!(tcp->flags & TCB_BPTSET)) {
1823 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1824 return -1;
1825 }
1826 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1827 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1828 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1829 return -1;
1830 }
1831 tcp->flags &= ~TCB_BPTSET;
1832
1833#if !LOOPA
1834 /*
1835 * Since we don't have a single instruction breakpoint, we may have
1836 * to adjust the program counter after removing the our `breakpoint'.
1837 */
1838 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1839 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1840 return -1;
1841 }
1842 if ((regs.r_pc < tcp->baddr) ||
1843 (regs.r_pc > tcp->baddr + 4)) {
1844 /* The breakpoint has not been reached yet */
1845 if (debug)
1846 fprintf(stderr,
1847 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1848 regs.r_pc, tcp->parent->baddr);
1849 return 0;
1850 }
1851 if (regs.r_pc != tcp->baddr)
1852 if (debug)
1853 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1854 regs.r_pc, tcp->baddr);
1855
1856 regs.r_pc = tcp->baddr;
1857 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1858 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1859 return -1;
1860 }
1861#endif /* LOOPA */
1862#endif /* SPARC */
1863#endif /* SUNOS4 */
1864
1865 return 0;
1866}
1867
Roland McGrathd81f1d92003-01-09 06:53:34 +00001868#endif
1869
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001870#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871
1872#ifdef SUNOS4
1873
1874static int
1875getex(pid, hdr)
1876int pid;
1877struct exec *hdr;
1878{
1879 int n;
1880
1881 for (n = 0; n < sizeof *hdr; n += 4) {
1882 long res;
1883 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1884 return -1;
1885 memcpy(((char *) hdr) + n, &res, 4);
1886 }
1887 if (debug) {
1888 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1889 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1890 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1891 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1892 }
1893 return 0;
1894}
1895
1896int
1897fixvfork(tcp)
1898struct tcb *tcp;
1899{
1900 int pid = tcp->pid;
1901 /*
1902 * Change `vfork' in a freshly exec'ed dynamically linked
1903 * executable's (internal) symbol table to plain old `fork'
1904 */
1905
1906 struct exec hdr;
1907 struct link_dynamic dyn;
1908 struct link_dynamic_2 ld;
1909 char *strtab, *cp;
1910
1911 if (getex(pid, &hdr) < 0)
1912 return -1;
1913 if (!hdr.a_dynamic)
1914 return -1;
1915
1916 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1917 fprintf(stderr, "Cannot read DYNAMIC\n");
1918 return -1;
1919 }
1920 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1921 fprintf(stderr, "Cannot read link_dynamic_2\n");
1922 return -1;
1923 }
1924 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1925 fprintf(stderr, "fixvfork: out of memory\n");
1926 return -1;
1927 }
1928 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1929 (int)ld.ld_symb_size, strtab) < 0)
1930 goto err;
1931
1932#if 0
1933 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1934 fprintf(stderr, "[symbol: %s]\n", cp);
1935 cp += strlen(cp)+1;
1936 }
1937 return 0;
1938#endif
1939 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1940 if (strcmp(cp, "_vfork") == 0) {
1941 if (debug)
1942 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1943 strcpy(cp, "_fork");
1944 break;
1945 }
1946 cp += strlen(cp)+1;
1947 }
1948 if (cp < strtab + ld.ld_symb_size)
1949 /*
1950 * Write entire symbol table back to avoid
1951 * memory alignment bugs in ptrace
1952 */
1953 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1954 (int)ld.ld_symb_size, strtab) < 0)
1955 goto err;
1956
1957 free(strtab);
1958 return 0;
1959
1960err:
1961 free(strtab);
1962 return -1;
1963}
1964
1965#endif /* SUNOS4 */