blob: a1e8cc6cb887b65c63da373cf7084d8fd754e861 [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 McGrathe1e584b2003-06-02 19:18:58 +0000977#elif defined(SHMEDIA)
978 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);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001032#elif defined(IA62)
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 McGrathe1e584b2003-06-02 19:18:58 +00001095#elif defined(SHMEDIA)
1096 long pc;
1097
1098 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1099 tprintf ("[????????] ");
1100 return;
1101 }
1102 tprintf("[%08lx] ", pc);
1103
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001104#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105#endif /* LINUX */
1106
1107#ifdef SUNOS4
1108 struct regs regs;
1109
1110 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1111 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1112 tprintf("[????????] ");
1113 return;
1114 }
1115 tprintf("[%08x] ", regs.r_o7);
1116#endif /* SUNOS4 */
1117
1118#ifdef SVR4
1119 /* XXX */
1120 tprintf("[????????] ");
1121#endif
1122
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001123#ifdef FREEBSD
1124 struct reg regs;
1125 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1126 tprintf("[%08x] ", regs.r_eip);
1127#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128}
1129
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001130#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131
Roland McGrathd81f1d92003-01-09 06:53:34 +00001132#if defined LINUX
1133
1134#include <sys/syscall.h>
1135#ifndef CLONE_PTRACE
1136# define CLONE_PTRACE 0x00002000
1137#endif
1138
1139#ifdef IA64
1140
1141typedef unsigned long *arg_setup_state;
1142
1143static int
1144arg_setup(struct tcb *tcp, arg_setup_state *state)
1145{
1146 unsigned long *bsp, cfm, sof, sol;
1147
1148 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1149 return -1;
1150 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1151 return -1;
1152
1153 sof = (cfm >> 0) & 0x7f;
1154 sol = (cfm >> 7) & 0x7f;
1155 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1156
1157 *state = bsp;
1158 return 0;
1159}
1160
1161# define arg_finish_change(tcp, state) 0
1162
1163#ifdef SYS_fork
1164static int
1165get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1166{
1167 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
1168 sizeof(long), (void *) valp);
1169}
1170
1171static int
1172get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1173{
1174 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
1175 sizeof(long), (void *) valp);
1176}
1177#endif
1178
1179static int
1180set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1181{
1182 unsigned long *ap;
1183 ap = ia64_rse_skip_regs(*state, 0);
1184 errno = 0;
1185 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1186 return errno ? -1 : 0;
1187}
1188
1189static int
1190set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1191{
1192 unsigned long *ap;
1193 ap = ia64_rse_skip_regs(*state, 1);
1194 errno = 0;
1195 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1196 return errno ? -1 : 0;
1197}
1198
1199#elif defined (SPARC)
1200
1201typedef struct regs arg_setup_state;
1202
1203# define arg_setup(tcp, state) \
1204 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1205# define arg_finish_change(tcp, state) \
1206 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1207
1208# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1209# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1210# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1211# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001212# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001213
1214#else
1215
1216# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001217/* Note: this is only true for the `clone' system call, which handles
1218 arguments specially. We could as well say that its first two arguments
1219 are swapped relative to other architectures, but that would just be
1220 another #ifdef in the calls. */
1221# define arg0_offset PT_GPR3
1222# define arg1_offset PT_ORIGGPR2
1223# define restore_arg0(tcp, state, val) ((void) (state), 0)
1224# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001225# elif defined (ALPHA) || defined (MIPS)
1226# define arg0_offset REG_A0
1227# define arg1_offset (REG_A0+1)
1228# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001229# define arg0_offset (sizeof(unsigned long)*PT_R3)
1230# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001231# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001232# elif defined (HPPA)
1233# define arg0_offset PT_GR26
1234# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001235# elif defined (X86_64)
1236# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1237# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001238# elif defined (SH)
1239# define arg0_offset (4*(REG_REG0+4))
1240# define arg1_offset (4*(REG_REG0+5))
Roland McGrathe1e584b2003-06-02 19:18:58 +00001241# elif defined (SHMEDIA)
1242 /* ABI defines arg0 & 1 in r2 & r3 */
1243# define arg0_offset (REG_OFFSET+16)
1244# define arg1_offset (REG_OFFSET+24)
1245# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001246# else
1247# define arg0_offset 0
1248# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001249# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001250# define restore_arg0(tcp, state, val) 0
1251# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001252# endif
1253
1254typedef int arg_setup_state;
1255
1256# define arg_setup(tcp, state) (0)
1257# define arg_finish_change(tcp, state) 0
1258# define get_arg0(tcp, cookie, valp) \
1259 (upeek ((tcp)->pid, arg0_offset, (valp)))
1260# define get_arg1(tcp, cookie, valp) \
1261 (upeek ((tcp)->pid, arg1_offset, (valp)))
1262
1263static int
1264set_arg0 (struct tcb *tcp, void *cookie, long val)
1265{
1266 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1267}
1268
1269static int
1270set_arg1 (struct tcb *tcp, void *cookie, long val)
1271{
1272 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1273}
1274
1275#endif
1276
Roland McGrathe1df47f2003-01-14 09:46:15 +00001277#ifndef restore_arg0
1278# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1279#endif
1280#ifndef restore_arg1
1281# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1282#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283
1284int
1285setbpt(tcp)
1286struct tcb *tcp;
1287{
1288 extern int change_syscall(struct tcb *, int);
1289 arg_setup_state state;
1290
1291 if (tcp->flags & TCB_BPTSET) {
1292 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1293 return -1;
1294 }
1295
1296 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001297#ifdef SYS_vfork
1298 case SYS_vfork:
1299#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001300#ifdef SYS_fork
1301 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001302#endif
1303#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001304 if (arg_setup (tcp, &state) < 0
1305 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1306 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1307 || change_syscall(tcp, SYS_clone) < 0
1308 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1309 || set_arg1 (tcp, &state, 0) < 0
1310 || arg_finish_change (tcp, &state) < 0)
1311 return -1;
1312 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1313 tcp->u_arg[1] = 0;
1314 tcp->flags |= TCB_BPTSET;
1315 return 0;
1316#endif
1317
1318 case SYS_clone:
1319#ifdef SYS_clone2
1320 case SYS_clone2:
1321#endif
1322 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1323 && (arg_setup (tcp, &state) < 0
1324 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1325 || arg_finish_change (tcp, &state) < 0))
1326 return -1;
1327 tcp->flags |= TCB_BPTSET;
1328 tcp->inst[0] = tcp->u_arg[0];
1329 tcp->inst[1] = tcp->u_arg[1];
1330 return 0;
1331
1332 default:
1333 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1334 tcp->scno, tcp->pid);
1335 break;
1336 }
1337
1338 return -1;
1339}
1340
1341int
1342clearbpt(tcp)
1343struct tcb *tcp;
1344{
1345 arg_setup_state state;
1346 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001347 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1348 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001349 || arg_finish_change (tcp, &state))
1350 return -1;
1351 tcp->flags &= ~TCB_BPTSET;
1352 return 0;
1353}
1354
1355#else
1356
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001357int
1358setbpt(tcp)
1359struct tcb *tcp;
1360{
1361
1362#ifdef LINUX
1363#ifdef SPARC
1364 /* We simply use the SunOS breakpoint code. */
1365
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001366 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001367#define LOOPA 0x30800000 /* ba,a 0 */
1368
1369 if (tcp->flags & TCB_BPTSET) {
1370 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1371 return -1;
1372 }
1373 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1374 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1375 return -1;
1376 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001377 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378 errno = 0;
1379 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1380 if(errno) {
1381 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1382 return -1;
1383 }
1384
1385 /*
1386 * XXX - BRUTAL MODE ON
1387 * We cannot set a real BPT in the child, since it will not be
1388 * traced at the moment it will reach the trap and would probably
1389 * die with a core dump.
1390 * Thus, we are force our way in by taking out two instructions
1391 * and insert an eternal loop instead, in expectance of the SIGSTOP
1392 * generated by out PTRACE_ATTACH.
1393 * Of cause, if we evaporate ourselves in the middle of all this...
1394 */
1395 errno = 0;
1396 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1397 if(errno) {
1398 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1399 return -1;
1400 }
1401 tcp->flags |= TCB_BPTSET;
1402
1403#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001404#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001405 if (ia32) {
1406# define LOOP 0x0000feeb
1407 if (tcp->flags & TCB_BPTSET) {
1408 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1409 tcp->pid);
1410 return -1;
1411 }
1412 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1413 return -1;
1414 if (debug)
1415 fprintf(stderr, "[%d] setting bpt at %lx\n",
1416 tcp->pid, tcp->baddr);
1417 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1418 (char *) tcp->baddr, 0);
1419 if (errno) {
1420 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1421 return -1;
1422 }
1423 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1424 if (errno) {
1425 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1426 return -1;
1427 }
1428 tcp->flags |= TCB_BPTSET;
1429 } else {
1430 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001431 * Our strategy here is to replace the bundle that
1432 * contained the clone() syscall with a bundle of the
1433 * form:
1434 *
1435 * { 1: br 1b; br 1b; br 1b }
1436 *
1437 * This ensures that the newly forked child will loop
1438 * endlessly until we've got a chance to attach to it.
1439 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001440# define LOOP0 0x0000100000000017
1441# define LOOP1 0x4000000000200000
1442 unsigned long addr, ipsr;
1443 pid_t pid;
1444
1445 pid = tcp->pid;
1446 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1447 return -1;
1448 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1449 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001450 /* store "ri" in low two bits */
1451 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001452
1453 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001454 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1455 0);
1456 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1457 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001458 if (errno) {
1459 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1460 return -1;
1461 }
1462
1463 errno = 0;
1464 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1465 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1466 if (errno) {
1467 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1468 return -1;
1469 }
1470 tcp->flags |= TCB_BPTSET;
1471 }
1472#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001473
Michal Ludvig0e035502002-09-23 15:41:01 +00001474#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475#define LOOP 0x0000feeb
1476#elif defined (M68K)
1477#define LOOP 0x60fe0000
1478#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001479#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001481#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001483#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001484#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001485#define LOOP 0x1000ffff
1486#elif defined(S390)
1487#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001488#elif defined(S390X)
1489#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001490#elif defined(HPPA)
1491#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001492#elif defined(SH)
1493#ifdef __LITTLE_ENDIAN__
1494#define LOOP 0x0000affe
1495#else
1496#define LOOP 0xfeaf0000
1497#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498#else
1499#error unknown architecture
1500#endif
1501
1502 if (tcp->flags & TCB_BPTSET) {
1503 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1504 return -1;
1505 }
1506#if defined (I386)
1507 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1508 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001509#elif defined (X86_64)
1510 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1511 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001512#elif defined (M68K)
1513 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1514 return -1;
1515#elif defined (ALPHA)
1516 return -1;
1517#elif defined (ARM)
1518 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001519#elif defined (MIPS)
1520 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001521#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001522 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001524#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001525 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1526 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001527#elif defined(HPPA)
1528 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1529 return -1;
1530 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001531#elif defined(SH)
1532 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1533 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534#else
1535#error unknown architecture
1536#endif
1537 if (debug)
1538 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1539 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1540 if (errno) {
1541 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1542 return -1;
1543 }
1544 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1545 if (errno) {
1546 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1547 return -1;
1548 }
1549 tcp->flags |= TCB_BPTSET;
1550
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001551#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552#endif /* SPARC */
1553#endif /* LINUX */
1554
1555#ifdef SUNOS4
1556#ifdef SPARC /* This code is slightly sparc specific */
1557
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001558 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001559#define BPT 0x91d02001 /* ta 1 */
1560#define LOOP 0x10800000 /* ba 0 */
1561#define LOOPA 0x30800000 /* ba,a 0 */
1562#define NOP 0x01000000
1563#if LOOPA
1564 static int loopdeloop[1] = {LOOPA};
1565#else
1566 static int loopdeloop[2] = {LOOP, NOP};
1567#endif
1568
1569 if (tcp->flags & TCB_BPTSET) {
1570 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1571 return -1;
1572 }
1573 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1574 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1575 return -1;
1576 }
1577 tcp->baddr = regs.r_o7 + 8;
1578 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1579 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1580 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1581 return -1;
1582 }
1583
1584 /*
1585 * XXX - BRUTAL MODE ON
1586 * We cannot set a real BPT in the child, since it will not be
1587 * traced at the moment it will reach the trap and would probably
1588 * die with a core dump.
1589 * Thus, we are force our way in by taking out two instructions
1590 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1591 * generated by out PTRACE_ATTACH.
1592 * Of cause, if we evaporate ourselves in the middle of all this...
1593 */
1594 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1595 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1596 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1597 return -1;
1598 }
1599 tcp->flags |= TCB_BPTSET;
1600
1601#endif /* SPARC */
1602#endif /* SUNOS4 */
1603
1604 return 0;
1605}
1606
1607int
1608clearbpt(tcp)
1609struct tcb *tcp;
1610{
1611
1612#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001613#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001615#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001617#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001619#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001620 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001621#elif defined(HPPA)
1622 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001623#elif defined(SH)
1624 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001625#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626
1627#ifdef SPARC
1628 /* Again, we borrow the SunOS breakpoint code. */
1629 if (!(tcp->flags & TCB_BPTSET)) {
1630 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1631 return -1;
1632 }
1633 errno = 0;
1634 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1635 if(errno) {
1636 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1637 return -1;
1638 }
1639 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001640#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001641 if (ia32) {
1642 unsigned long addr;
1643
1644 if (debug)
1645 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1646 if (!(tcp->flags & TCB_BPTSET)) {
1647 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1648 return -1;
1649 }
1650 errno = 0;
1651 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1652 if (errno) {
1653 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1654 return -1;
1655 }
1656 tcp->flags &= ~TCB_BPTSET;
1657
1658 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1659 return -1;
1660 if (addr != tcp->baddr) {
1661 /* The breakpoint has not been reached yet. */
1662 if (debug)
1663 fprintf(stderr,
1664 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1665 addr, tcp->baddr);
1666 return 0;
1667 }
1668 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001669 unsigned long addr, ipsr;
1670 pid_t pid;
1671
1672 pid = tcp->pid;
1673
1674 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1675 return -1;
1676 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1677 return -1;
1678
1679 /* restore original bundle: */
1680 errno = 0;
1681 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1682 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1683 if (errno) {
1684 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1685 return -1;
1686 }
1687
1688 /* restore original "ri" in ipsr: */
1689 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1690 errno = 0;
1691 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1692 if (errno) {
1693 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1694 return -1;
1695 }
1696
1697 tcp->flags &= ~TCB_BPTSET;
1698
1699 if (addr != (tcp->baddr & ~0x3)) {
1700 /* the breakpoint has not been reached yet. */
1701 if (debug)
1702 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1703 addr, tcp->baddr);
1704 return 0;
1705 }
1706 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001707#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708
1709 if (debug)
1710 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1711 if (!(tcp->flags & TCB_BPTSET)) {
1712 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1713 return -1;
1714 }
1715 errno = 0;
1716 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1717 if (errno) {
1718 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1719 return -1;
1720 }
1721 tcp->flags &= ~TCB_BPTSET;
1722
1723#ifdef I386
1724 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1725 return -1;
1726 if (eip != tcp->baddr) {
1727 /* The breakpoint has not been reached yet. */
1728 if (debug)
1729 fprintf(stderr,
1730 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1731 eip, tcp->baddr);
1732 return 0;
1733 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001734#elif defined(X86_64)
1735 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1736 return -1;
1737 if (eip != tcp->baddr) {
1738 /* The breakpoint has not been reached yet. */
1739 if (debug)
1740 fprintf(stderr,
1741 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1742 eip, tcp->baddr);
1743 return 0;
1744 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001745#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001746 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001747 return -1;
1748 if (pc != tcp->baddr) {
1749 /* The breakpoint has not been reached yet. */
1750 if (debug)
1751 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1752 pc, tcp->baddr);
1753 return 0;
1754 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001755#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1757 return -1;
1758 if (pc != tcp->baddr) {
1759 /* The breakpoint has not been reached yet. */
1760 if (debug)
1761 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1762 pc, tcp->baddr);
1763 return 0;
1764 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001765#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1767 return -1;
1768 if (pc != tcp->baddr) {
1769 /* The breakpoint has not been reached yet. */
1770 if (debug)
1771 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1772 pc, tcp->baddr);
1773 return 0;
1774 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001775#elif defined(HPPA)
1776 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1777 return -1;
1778 iaoq &= ~0x03;
1779 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1780 /* The breakpoint has not been reached yet. */
1781 if (debug)
1782 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1783 iaoq, tcp->baddr);
1784 return 0;
1785 }
1786 iaoq = tcp->baddr | 3;
1787 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1788 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1789 * has no significant effect.
1790 */
1791 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1792 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001793#elif defined(SH)
1794 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1795 return -1;
1796 if (pc != tcp->baddr) {
1797 /* The breakpoint has not been reached yet. */
1798 if (debug)
1799 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1800 pc, tcp->baddr);
1801 return 0;
1802 }
1803
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001804#endif /* arch */
1805#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001806#endif /* LINUX */
1807
1808#ifdef SUNOS4
1809#ifdef SPARC
1810
1811#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001812 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813#endif
1814
1815 if (!(tcp->flags & TCB_BPTSET)) {
1816 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1817 return -1;
1818 }
1819 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1820 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1821 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1822 return -1;
1823 }
1824 tcp->flags &= ~TCB_BPTSET;
1825
1826#if !LOOPA
1827 /*
1828 * Since we don't have a single instruction breakpoint, we may have
1829 * to adjust the program counter after removing the our `breakpoint'.
1830 */
1831 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1832 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1833 return -1;
1834 }
1835 if ((regs.r_pc < tcp->baddr) ||
1836 (regs.r_pc > tcp->baddr + 4)) {
1837 /* The breakpoint has not been reached yet */
1838 if (debug)
1839 fprintf(stderr,
1840 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1841 regs.r_pc, tcp->parent->baddr);
1842 return 0;
1843 }
1844 if (regs.r_pc != tcp->baddr)
1845 if (debug)
1846 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1847 regs.r_pc, tcp->baddr);
1848
1849 regs.r_pc = tcp->baddr;
1850 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1851 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1852 return -1;
1853 }
1854#endif /* LOOPA */
1855#endif /* SPARC */
1856#endif /* SUNOS4 */
1857
1858 return 0;
1859}
1860
Roland McGrathd81f1d92003-01-09 06:53:34 +00001861#endif
1862
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001863#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001864
1865#ifdef SUNOS4
1866
1867static int
1868getex(pid, hdr)
1869int pid;
1870struct exec *hdr;
1871{
1872 int n;
1873
1874 for (n = 0; n < sizeof *hdr; n += 4) {
1875 long res;
1876 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1877 return -1;
1878 memcpy(((char *) hdr) + n, &res, 4);
1879 }
1880 if (debug) {
1881 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1882 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1883 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1884 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1885 }
1886 return 0;
1887}
1888
1889int
1890fixvfork(tcp)
1891struct tcb *tcp;
1892{
1893 int pid = tcp->pid;
1894 /*
1895 * Change `vfork' in a freshly exec'ed dynamically linked
1896 * executable's (internal) symbol table to plain old `fork'
1897 */
1898
1899 struct exec hdr;
1900 struct link_dynamic dyn;
1901 struct link_dynamic_2 ld;
1902 char *strtab, *cp;
1903
1904 if (getex(pid, &hdr) < 0)
1905 return -1;
1906 if (!hdr.a_dynamic)
1907 return -1;
1908
1909 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1910 fprintf(stderr, "Cannot read DYNAMIC\n");
1911 return -1;
1912 }
1913 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1914 fprintf(stderr, "Cannot read link_dynamic_2\n");
1915 return -1;
1916 }
1917 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1918 fprintf(stderr, "fixvfork: out of memory\n");
1919 return -1;
1920 }
1921 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1922 (int)ld.ld_symb_size, strtab) < 0)
1923 goto err;
1924
1925#if 0
1926 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1927 fprintf(stderr, "[symbol: %s]\n", cp);
1928 cp += strlen(cp)+1;
1929 }
1930 return 0;
1931#endif
1932 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1933 if (strcmp(cp, "_vfork") == 0) {
1934 if (debug)
1935 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1936 strcpy(cp, "_fork");
1937 break;
1938 }
1939 cp += strlen(cp)+1;
1940 }
1941 if (cp < strtab + ld.ld_symb_size)
1942 /*
1943 * Write entire symbol table back to avoid
1944 * memory alignment bugs in ptrace
1945 */
1946 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1947 (int)ld.ld_symb_size, strtab) < 0)
1948 goto err;
1949
1950 free(strtab);
1951 return 0;
1952
1953err:
1954 free(strtab);
1955 return -1;
1956}
1957
1958#endif /* SUNOS4 */