blob: d4cc290cdf511a7ba496bdcf481cbd33e7bcbda1 [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
Roland McGrathce9f0742004-03-01 21:29:22 +000066# ifdef HAVE_STRUCT_IA64_FPREG
67# define ia64_fpreg XXX_ia64_fpreg
68# endif
69# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70# define pt_all_user_regs XXX_pt_all_user_regs
71# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000072#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000073# undef ia64_fpreg
74# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000075#endif
76
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78#include <sys/utsname.h>
79#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000081#if defined(LINUX) && defined(SPARC)
82
Roland McGrath4db26242003-01-30 20:15:19 +000083# define fpq kernel_fpq
84# define fq kernel_fq
85# define fpu kernel_fpu
86# include <asm/reg.h>
87# undef fpq
88# undef fq
89# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000090
91#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092
93#include <linux/unistd.h>
94
95#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
96 type5,arg5,syscall) \
97type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
98{ \
99 long __res; \
100\
101__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
102 "or %%g0, %2, %%o1\n\t" \
103 "or %%g0, %3, %%o2\n\t" \
104 "or %%g0, %4, %%o3\n\t" \
105 "or %%g0, %5, %%o4\n\t" \
106 "or %%g0, %6, %%g1\n\t" \
107 "t 0x10\n\t" \
108 "bcc 1f\n\t" \
109 "or %%g0, %%o0, %0\n\t" \
110 "sub %%g0, %%o0, %0\n\t" \
111 "1:\n\t" \
112 : "=r" (__res) \
113 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
114 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
115 "i" (__NR_##syscall) \
116 : "g1", "o0", "o1", "o2", "o3", "o4"); \
117if (__res>=0) \
118 return (type) __res; \
119errno = -__res; \
120return -1; \
121}
122
123static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
124
125#define _ptrace
126
127#endif
128
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000129#endif
130
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131/* macros */
132#ifndef MAX
133#define MAX(a,b) (((a) > (b)) ? (a) : (b))
134#endif
135#ifndef MIN
136#define MIN(a,b) (((a) < (b)) ? (a) : (b))
137#endif
138
139void
140tv_tv(tv, a, b)
141struct timeval *tv;
142int a;
143int b;
144{
145 tv->tv_sec = a;
146 tv->tv_usec = b;
147}
148
149int
150tv_nz(a)
151struct timeval *a;
152{
153 return a->tv_sec || a->tv_usec;
154}
155
156int
157tv_cmp(a, b)
158struct timeval *a, *b;
159{
160 if (a->tv_sec < b->tv_sec
161 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
162 return -1;
163 if (a->tv_sec > b->tv_sec
164 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
165 return 1;
166 return 0;
167}
168
169double
170tv_float(tv)
171struct timeval *tv;
172{
173 return tv->tv_sec + tv->tv_usec/1000000.0;
174}
175
176void
177tv_add(tv, a, b)
178struct timeval *tv, *a, *b;
179{
180 tv->tv_sec = a->tv_sec + b->tv_sec;
181 tv->tv_usec = a->tv_usec + b->tv_usec;
182 if (tv->tv_usec > 1000000) {
183 tv->tv_sec++;
184 tv->tv_usec -= 1000000;
185 }
186}
187
188void
189tv_sub(tv, a, b)
190struct timeval *tv, *a, *b;
191{
192 tv->tv_sec = a->tv_sec - b->tv_sec;
193 tv->tv_usec = a->tv_usec - b->tv_usec;
194 if (((long) tv->tv_usec) < 0) {
195 tv->tv_sec--;
196 tv->tv_usec += 1000000;
197 }
198}
199
200void
201tv_div(tv, a, n)
202struct timeval *tv, *a;
203int n;
204{
205 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
206 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
207 tv->tv_usec %= 1000000;
208}
209
210void
211tv_mul(tv, a, n)
212struct timeval *tv, *a;
213int n;
214{
215 tv->tv_usec = a->tv_usec * n;
216 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
217 tv->tv_usec %= 1000000;
218}
219
220char *
221xlookup(xlat, val)
222struct xlat *xlat;
223int val;
224{
225 for (; xlat->str != NULL; xlat++)
226 if (xlat->val == val)
227 return xlat->str;
228 return NULL;
229}
230
231/*
232 * Print entry in struct xlat table, if there.
233 */
234void
235printxval(xlat, val, dflt)
236struct xlat *xlat;
237int val;
238char *dflt;
239{
240 char *str = xlookup(xlat, val);
241
242 if (str)
243 tprintf("%s", str);
244 else
245 tprintf("%#x /* %s */", val, dflt);
246}
247
248/*
249 * Interpret `xlat' as an array of flags
250 * print the entries whose bits are on in `flags'
251 * return # of flags printed.
252 */
253int
254addflags(xlat, flags)
255struct xlat *xlat;
256int flags;
257{
258 int n;
259
260 for (n = 0; xlat->str; xlat++) {
261 if (xlat->val && (flags & xlat->val) == xlat->val) {
262 tprintf("|%s", xlat->str);
263 flags &= ~xlat->val;
264 n++;
265 }
266 }
267 if (flags) {
268 tprintf("|%#x", flags);
269 n++;
270 }
271 return n;
272}
273
274int
275printflags(xlat, flags)
276struct xlat *xlat;
277int flags;
278{
279 int n;
280 char *sep;
281
282 if (flags == 0 && xlat->val == 0) {
283 tprintf("%s", xlat->str);
284 return 1;
285 }
286
287 sep = "";
288 for (n = 0; xlat->str; xlat++) {
289 if (xlat->val && (flags & xlat->val) == xlat->val) {
290 tprintf("%s%s", sep, xlat->str);
291 flags &= ~xlat->val;
292 sep = "|";
293 n++;
294 }
295 }
296 if (flags) {
297 tprintf("%s%#x", sep, flags);
298 n++;
299 }
300 return n;
301}
302
303void
304printnum(tcp, addr, fmt)
305struct tcb *tcp;
306long addr;
307char *fmt;
308{
Roland McGratheb285352003-01-14 09:59:00 +0000309 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000310
311 if (!addr) {
312 tprintf("NULL");
313 return;
314 }
315 if (umove(tcp, addr, &num) < 0) {
316 tprintf("%#lx", addr);
317 return;
318 }
319 tprintf("[");
320 tprintf(fmt, num);
321 tprintf("]");
322}
323
Roland McGrath6bc12202003-11-13 22:32:27 +0000324void
325printuid(text, uid)
326const char *text;
327unsigned long uid;
328{
329 tprintf("%s", text);
330 tprintf((uid == -1) ? "%ld" : "%lu", uid);
331}
332
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333static char path[MAXPATHLEN + 1];
334
335void
336string_quote(str)
337char *str;
338{
339 char buf[2 * MAXPATHLEN + 1];
340 char *s;
341
342 if (!strpbrk(str, "\"\'\\")) {
343 tprintf("\"%s\"", str);
344 return;
345 }
346 for (s = buf; *str; str++) {
347 switch (*str) {
348 case '\"': case '\'': case '\\':
349 *s++ = '\\'; *s++ = *str; break;
350 default:
351 *s++ = *str; break;
352 }
353 }
354 *s = '\0';
355 tprintf("\"%s\"", buf);
356}
357
358void
359printpath(tcp, addr)
360struct tcb *tcp;
361long addr;
362{
363 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
364 tprintf("%#lx", addr);
365 else
366 string_quote(path);
367 return;
368}
369
370void
371printpathn(tcp, addr, n)
372struct tcb *tcp;
373long addr;
374int n;
375{
376 if (umovestr(tcp, addr, n, path) < 0)
377 tprintf("%#lx", addr);
378 else {
379 path[n] = '\0';
380 string_quote(path);
381 }
382}
383
384void
385printstr(tcp, addr, len)
386struct tcb *tcp;
387long addr;
388int len;
389{
390 static unsigned char *str = NULL;
391 static char *outstr;
392 int i, n, c, usehex;
393 char *s, *outend;
394
395 if (!addr) {
396 tprintf("NULL");
397 return;
398 }
399 if (!str) {
400 if ((str = malloc(max_strlen)) == NULL
401 || (outstr = malloc(2*max_strlen)) == NULL) {
402 fprintf(stderr, "printstr: no memory\n");
403 tprintf("%#lx", addr);
404 return;
405 }
406 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000407 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000408 if (len < 0) {
409 n = max_strlen;
410 if (umovestr(tcp, addr, n, (char *) str) < 0) {
411 tprintf("%#lx", addr);
412 return;
413 }
414 }
415 else {
416 n = MIN(len, max_strlen);
417 if (umoven(tcp, addr, n, (char *) str) < 0) {
418 tprintf("%#lx", addr);
419 return;
420 }
421 }
422
423 usehex = 0;
424 if (xflag > 1)
425 usehex = 1;
426 else if (xflag) {
427 for (i = 0; i < n; i++) {
428 c = str[i];
429 if (len < 0 && c == '\0')
430 break;
431 if (!isprint(c) && !isspace(c)) {
432 usehex = 1;
433 break;
434 }
435 }
436 }
437
438 s = outstr;
439 *s++ = '\"';
440
441 if (usehex) {
442 for (i = 0; i < n; i++) {
443 c = str[i];
444 if (len < 0 && c == '\0')
445 break;
446 sprintf(s, "\\x%02x", c);
447 s += 4;
448 if (s > outend)
449 break;
450 }
451 }
452 else {
453 for (i = 0; i < n; i++) {
454 c = str[i];
455 if (len < 0 && c == '\0')
456 break;
457 switch (c) {
458 case '\"': case '\'': case '\\':
459 *s++ = '\\'; *s++ = c; break;
460 case '\f':
461 *s++ = '\\'; *s++ = 'f'; break;
462 case '\n':
463 *s++ = '\\'; *s++ = 'n'; break;
464 case '\r':
465 *s++ = '\\'; *s++ = 'r'; break;
466 case '\t':
467 *s++ = '\\'; *s++ = 't'; break;
468 case '\v':
469 *s++ = '\\'; *s++ = 'v'; break;
470 default:
471 if (isprint(c))
472 *s++ = c;
473 else if (i < n - 1 && isdigit(str[i + 1])) {
474 sprintf(s, "\\%03o", c);
475 s += 4;
476 }
477 else {
478 sprintf(s, "\\%o", c);
479 s += strlen(s);
480 }
481 break;
482 }
483 if (s > outend)
484 break;
485 }
486 }
487
488 *s++ = '\"';
489 if (i < len || (len < 0 && (i == n || s > outend))) {
490 *s++ = '.'; *s++ = '.'; *s++ = '.';
491 }
492 *s = '\0';
493 tprintf("%s", outstr);
494}
495
John Hughes1d08dcf2001-07-10 13:48:44 +0000496#if HAVE_SYS_UIO_H
497void
498dumpiov(tcp, len, addr)
499struct tcb * tcp;
500int len;
501long addr;
502{
503 struct iovec *iov;
504 int i;
505
Roland McGrath1e85cf92002-12-16 20:40:54 +0000506
John Hughes1d08dcf2001-07-10 13:48:44 +0000507 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
508 fprintf(stderr, "dump: No memory");
509 return;
510 }
511 if (umoven(tcp, addr,
512 len * sizeof *iov, (char *) iov) >= 0) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000513
John Hughes1d08dcf2001-07-10 13:48:44 +0000514 for (i = 0; i < len; i++) {
515 /* include the buffer number to make it easy to
516 * match up the trace with the source */
517 tprintf(" * %lu bytes in buffer %d\n",
518 (unsigned long)iov[i].iov_len, i);
519 dumpstr(tcp, (long) iov[i].iov_base,
520 iov[i].iov_len);
521 }
522 }
523 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000524
John Hughes1d08dcf2001-07-10 13:48:44 +0000525}
526#endif
527
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528void
529dumpstr(tcp, addr, len)
530struct tcb *tcp;
531long addr;
532int len;
533{
534 static int strsize = -1;
535 static unsigned char *str;
536 static char outstr[80];
537 char *s;
538 int i, j;
539
540 if (strsize < len) {
541 if (str)
542 free(str);
543 if ((str = malloc(len)) == NULL) {
544 fprintf(stderr, "dump: no memory\n");
545 return;
546 }
547 strsize = len;
548 }
549
550 if (umoven(tcp, addr, len, (char *) str) < 0)
551 return;
552
553 for (i = 0; i < len; i += 16) {
554 s = outstr;
555 sprintf(s, " | %05x ", i);
556 s += 9;
557 for (j = 0; j < 16; j++) {
558 if (j == 8)
559 *s++ = ' ';
560 if (i + j < len) {
561 sprintf(s, " %02x", str[i + j]);
562 s += 3;
563 }
564 else {
565 *s++ = ' '; *s++ = ' '; *s++ = ' ';
566 }
567 }
568 *s++ = ' '; *s++ = ' ';
569 for (j = 0; j < 16; j++) {
570 if (j == 8)
571 *s++ = ' ';
572 if (i + j < len) {
573 if (isprint(str[i + j]))
574 *s++ = str[i + j];
575 else
576 *s++ = '.';
577 }
578 else
579 *s++ = ' ';
580 }
581 tprintf("%s |\n", outstr);
582 }
583}
584
585#define PAGMASK (~(PAGSIZ - 1))
586/*
587 * move `len' bytes of data from process `pid'
588 * at address `addr' to our space at `laddr'
589 */
590int
591umoven(tcp, addr, len, laddr)
592struct tcb *tcp;
593long addr;
594int len;
595char *laddr;
596{
597
598#ifdef LINUX
599 int pid = tcp->pid;
600 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000601 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602 union {
603 long val;
604 char x[sizeof(long)];
605 } u;
606
607 if (addr & (sizeof(long) - 1)) {
608 /* addr not a multiple of sizeof(long) */
609 n = addr - (addr & -sizeof(long)); /* residue */
610 addr &= -sizeof(long); /* residue */
611 errno = 0;
612 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
613 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000614 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000615 /* Ran into 'end of memory' - stupid "printpath" */
616 return 0;
617 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000618 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000619 perror("ptrace: umoven");
620 return -1;
621 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000622 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000623 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
624 addr += sizeof(long), laddr += m, len -= m;
625 }
626 while (len) {
627 errno = 0;
628 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
629 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000630 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631 /* Ran into 'end of memory' - stupid "printpath" */
632 return 0;
633 }
Roland McGrath4db26242003-01-30 20:15:19 +0000634 if (addr != 0)
635 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000636 return -1;
637 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000638 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000639 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
640 addr += sizeof(long), laddr += m, len -= m;
641 }
642#endif /* LINUX */
643
644#ifdef SUNOS4
645 int pid = tcp->pid;
646#if 0
647 int n, m;
648 union {
649 long val;
650 char x[sizeof(long)];
651 } u;
652
653 if (addr & (sizeof(long) - 1)) {
654 /* addr not a multiple of sizeof(long) */
655 n = addr - (addr & -sizeof(long)); /* residue */
656 addr &= -sizeof(long); /* residue */
657 errno = 0;
658 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
659 if (errno) {
660 perror("umoven");
661 return -1;
662 }
663 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
664 addr += sizeof(long), laddr += m, len -= m;
665 }
666 while (len) {
667 errno = 0;
668 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
669 if (errno) {
670 perror("umoven");
671 return -1;
672 }
673 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
674 addr += sizeof(long), laddr += m, len -= m;
675 }
676#else /* !oldway */
677 int n;
678
679 while (len) {
680 n = MIN(len, PAGSIZ);
681 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
682 if (ptrace(PTRACE_READDATA, pid,
683 (char *) addr, len, laddr) < 0) {
684 perror("umoven: ptrace(PTRACE_READDATA, ...)");
685 abort();
686 return -1;
687 }
688 len -= n;
689 addr += n;
690 laddr += n;
691 }
692#endif /* !oldway */
693#endif /* SUNOS4 */
694
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000695#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000696#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000697 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000698#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000699 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000700#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000701 lseek(fd, addr, SEEK_SET);
702 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000703 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000704#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705
706 return 0;
707}
708
709/*
710 * like `umove' but make the additional effort of looking
711 * for a terminating zero byte.
712 */
713int
714umovestr(tcp, addr, len, laddr)
715struct tcb *tcp;
716long addr;
717int len;
718char *laddr;
719{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000720#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000721#ifdef HAVE_MP_PROCFS
722 int fd = tcp->pfd_as;
723#else
724 int fd = tcp->pfd;
725#endif
726 /* Some systems (e.g. FreeBSD) can be upset if we read off the
727 end of valid memory, avoid this by trying to read up
728 to page boundaries. But we don't know what a page is (and
729 getpagesize(2) (if it exists) doesn't necessarily return
730 hardware page size). Assume all pages >= 1024 (a-historical
731 I know) */
732
733 int page = 1024; /* How to find this? */
734 int move = page - (addr & (page - 1));
735 int left = len;
736
737 lseek(fd, addr, SEEK_SET);
738
739 while (left) {
740 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000741 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000742 return left != len ? 0 : -1;
743 if (memchr (laddr, 0, move)) break;
744 left -= move;
745 laddr += move;
746 addr += move;
747 move = page;
748 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000749#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000750 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000751 int pid = tcp->pid;
752 int i, n, m;
753 union {
754 long val;
755 char x[sizeof(long)];
756 } u;
757
758 if (addr & (sizeof(long) - 1)) {
759 /* addr not a multiple of sizeof(long) */
760 n = addr - (addr & -sizeof(long)); /* residue */
761 addr &= -sizeof(long); /* residue */
762 errno = 0;
763 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
764 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000765 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000766 /* Ran into 'end of memory' - stupid "printpath" */
767 return 0;
768 }
769 perror("umovestr");
770 return -1;
771 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000772 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000773 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
774 while (n & (sizeof(long) - 1))
775 if (u.x[n++] == '\0')
776 return 0;
777 addr += sizeof(long), laddr += m, len -= m;
778 }
779 while (len) {
780 errno = 0;
781 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
782 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000783 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000784 /* Ran into 'end of memory' - stupid "printpath" */
785 return 0;
786 }
787 perror("umovestr");
788 return -1;
789 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000790 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
792 for (i = 0; i < sizeof(long); i++)
793 if (u.x[i] == '\0')
794 return 0;
795
796 addr += sizeof(long), laddr += m, len -= m;
797 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000798#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000799 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000800}
801
802#ifdef LINUX
803#ifndef SPARC
804#define PTRACE_WRITETEXT 101
805#define PTRACE_WRITEDATA 102
806#endif /* !SPARC */
807#endif /* LINUX */
808
809#ifdef SUNOS4
810
811static int
812uload(cmd, pid, addr, len, laddr)
813int cmd;
814int pid;
815long addr;
816int len;
817char *laddr;
818{
819#if 0
820 int n;
821
822 while (len) {
823 n = MIN(len, PAGSIZ);
824 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
825 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
826 perror("uload: ptrace(PTRACE_WRITE, ...)");
827 return -1;
828 }
829 len -= n;
830 addr += n;
831 laddr += n;
832 }
833#else
834 int peek, poke;
835 int n, m;
836 union {
837 long val;
838 char x[sizeof(long)];
839 } u;
840
841 if (cmd == PTRACE_WRITETEXT) {
842 peek = PTRACE_PEEKTEXT;
843 poke = PTRACE_POKETEXT;
844 }
845 else {
846 peek = PTRACE_PEEKDATA;
847 poke = PTRACE_POKEDATA;
848 }
849 if (addr & (sizeof(long) - 1)) {
850 /* addr not a multiple of sizeof(long) */
851 n = addr - (addr & -sizeof(long)); /* residue */
852 addr &= -sizeof(long);
853 errno = 0;
854 u.val = ptrace(peek, pid, (char *) addr, 0);
855 if (errno) {
856 perror("uload: POKE");
857 return -1;
858 }
859 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
860 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
861 perror("uload: POKE");
862 return -1;
863 }
864 addr += sizeof(long), laddr += m, len -= m;
865 }
866 while (len) {
867 if (len < sizeof(long))
868 u.val = ptrace(peek, pid, (char *) addr, 0);
869 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
870 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
871 perror("uload: POKE");
872 return -1;
873 }
874 addr += sizeof(long), laddr += m, len -= m;
875 }
876#endif
877 return 0;
878}
879
880int
881tload(pid, addr, len, laddr)
882int pid;
883int addr, len;
884char *laddr;
885{
886 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
887}
888
889int
890dload(pid, addr, len, laddr)
891int pid;
892int addr;
893int len;
894char *laddr;
895{
896 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
897}
898
899#endif /* SUNOS4 */
900
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000901#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902
903int
904upeek(pid, off, res)
905int pid;
906long off;
907long *res;
908{
909 long val;
910
911#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
912 {
913 static int is_sun4m = -1;
914 struct utsname name;
915
916 /* Round up the usual suspects. */
917 if (is_sun4m == -1) {
918 if (uname(&name) < 0) {
919 perror("upeek: uname?");
920 exit(1);
921 }
922 is_sun4m = strcmp(name.machine, "sun4m") == 0;
923 if (is_sun4m) {
924 extern struct xlat struct_user_offsets[];
925 struct xlat *x;
926
927 for (x = struct_user_offsets; x->str; x++)
928 x->val += 1024;
929 }
930 }
931 if (is_sun4m)
932 off += 1024;
933 }
934#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
935 errno = 0;
936 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
937 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000938 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000939 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000940 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 return -1;
942 }
943 *res = val;
944 return 0;
945}
946
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000947#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948
949long
950getpc(tcp)
951struct tcb *tcp;
952{
953
954#ifdef LINUX
955 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000956#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
958 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000959#elif defined(X86_64)
960 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
961 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000962#elif defined(IA64)
963 if (upeek(tcp->pid, PT_B0, &pc) < 0)
964 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000965#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 if (upeek(tcp->pid, 4*15, &pc) < 0)
967 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000968#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000969 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000971#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
973 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000974#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975 if (upeek(tcp->pid, REG_PC, &pc) < 0)
976 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000977#elif defined(MIPS)
978 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
979 return -1;
980#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000981 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
983 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000984 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000985#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000986 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +0000987 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000988#elif defined(HPPA)
989 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
990 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000991#elif defined(SH)
992 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
993 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +0000994#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +0000995 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
996 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +0000997#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 return pc;
999#endif /* LINUX */
1000
1001#ifdef SUNOS4
1002 /*
1003 * Return current program counter for `pid'
1004 * Assumes PC is never 0xffffffff
1005 */
1006 struct regs regs;
1007
1008 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1009 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1010 return -1;
1011 }
1012 return regs.r_pc;
1013#endif /* SUNOS4 */
1014
1015#ifdef SVR4
1016 /* XXX */
1017 return 0;
1018#endif /* SVR4 */
1019
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001020#ifdef FREEBSD
1021 struct reg regs;
1022 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1023 return regs.r_eip;
1024#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001025}
1026
1027void
1028printcall(tcp)
1029struct tcb *tcp;
1030{
1031
1032#ifdef LINUX
1033#ifdef I386
1034 long eip;
1035
1036 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1037 tprintf("[????????] ");
1038 return;
1039 }
1040 tprintf("[%08lx] ", eip);
Michal Ludvig0e035502002-09-23 15:41:01 +00001041#elif defined(X86_64)
1042 long rip;
1043
1044 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1045 tprintf("[????????] ");
1046 return;
1047 }
1048 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001049#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001050 long ip;
1051
1052 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1053 tprintf("[????????] ");
1054 return;
1055 }
1056 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001057#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058 long pc;
1059
Roland McGratheb285352003-01-14 09:59:00 +00001060 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001061 tprintf ("[????????] ");
1062 return;
1063 }
1064 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001065#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066 long pc;
1067
1068 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1069 tprintf ("[????????] ");
1070 return;
1071 }
1072 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001073#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001074 long pc;
1075
1076 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1077 tprintf ("[????????] ");
1078 return;
1079 }
1080 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001081#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001082 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001083 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1084 tprintf("[????????] ");
1085 return;
1086 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001087 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001088#elif defined(HPPA)
1089 long pc;
1090
1091 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1092 tprintf ("[????????] ");
1093 return;
1094 }
1095 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001096#elif defined(MIPS)
1097 long pc;
1098
1099 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1100 tprintf ("[????????] ");
1101 return;
1102 }
1103 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001104#elif defined(SH)
1105 long pc;
1106
1107 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1108 tprintf ("[????????] ");
1109 return;
1110 }
1111 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001112#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001113 long pc;
1114
1115 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1116 tprintf ("[????????] ");
1117 return;
1118 }
1119 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001120#elif defined(ARM)
1121 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001122
Roland McGrathef388682003-06-03 23:28:59 +00001123 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1124 tprintf("[????????] ");
1125 return;
1126 }
1127 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001128#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129#endif /* LINUX */
1130
1131#ifdef SUNOS4
1132 struct regs regs;
1133
1134 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1135 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1136 tprintf("[????????] ");
1137 return;
1138 }
1139 tprintf("[%08x] ", regs.r_o7);
1140#endif /* SUNOS4 */
1141
1142#ifdef SVR4
1143 /* XXX */
1144 tprintf("[????????] ");
1145#endif
1146
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001147#ifdef FREEBSD
1148 struct reg regs;
1149 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1150 tprintf("[%08x] ", regs.r_eip);
1151#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152}
1153
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001154#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155
Roland McGrathd81f1d92003-01-09 06:53:34 +00001156#if defined LINUX
1157
1158#include <sys/syscall.h>
1159#ifndef CLONE_PTRACE
1160# define CLONE_PTRACE 0x00002000
1161#endif
1162
1163#ifdef IA64
1164
Roland McGrath08267b82004-02-20 22:56:43 +00001165/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1166 subsystem has them for x86... */
1167#define SYS_fork 2
1168#define SYS_vfork 190
1169
Roland McGrathd81f1d92003-01-09 06:53:34 +00001170typedef unsigned long *arg_setup_state;
1171
1172static int
1173arg_setup(struct tcb *tcp, arg_setup_state *state)
1174{
1175 unsigned long *bsp, cfm, sof, sol;
1176
Roland McGrath08267b82004-02-20 22:56:43 +00001177 if (ia32)
1178 return 0;
1179
Roland McGrathd81f1d92003-01-09 06:53:34 +00001180 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1181 return -1;
1182 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1183 return -1;
1184
1185 sof = (cfm >> 0) & 0x7f;
1186 sol = (cfm >> 7) & 0x7f;
1187 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1188
1189 *state = bsp;
1190 return 0;
1191}
1192
1193# define arg_finish_change(tcp, state) 0
1194
1195#ifdef SYS_fork
1196static int
1197get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1198{
Roland McGrath08267b82004-02-20 22:56:43 +00001199 int ret;
1200
1201 if (ia32)
1202 ret = upeek (tcp->pid, PT_R11, valp);
1203 else
1204 ret = umoven (tcp,
1205 (unsigned long) ia64_rse_skip_regs(*state, 0),
1206 sizeof(long), (void *) valp);
1207 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001208}
1209
1210static int
1211get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1212{
Roland McGrath08267b82004-02-20 22:56:43 +00001213 int ret;
1214
1215 if (ia32)
1216 ret = upeek (tcp->pid, PT_R9, valp);
1217 else
1218 ret = umoven (tcp,
1219 (unsigned long) ia64_rse_skip_regs(*state, 1),
1220 sizeof(long), (void *) valp);
1221 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001222}
1223#endif
1224
1225static int
1226set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1227{
Roland McGrath08267b82004-02-20 22:56:43 +00001228 int req = PTRACE_POKEDATA;
1229 void *ap;
1230
1231 if (ia32) {
1232 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1233 req = PTRACE_POKEUSER;
1234 } else
1235 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001236 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001237 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001238 return errno ? -1 : 0;
1239}
1240
1241static int
1242set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1243{
Roland McGrath08267b82004-02-20 22:56:43 +00001244 int req = PTRACE_POKEDATA;
1245 void *ap;
1246
1247 if (ia32) {
1248 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1249 req = PTRACE_POKEUSER;
1250 } else
1251 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001252 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001253 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001254 return errno ? -1 : 0;
1255}
1256
1257#elif defined (SPARC)
1258
1259typedef struct regs arg_setup_state;
1260
1261# define arg_setup(tcp, state) \
1262 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1263# define arg_finish_change(tcp, state) \
1264 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1265
1266# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1267# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1268# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1269# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001270# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001271
1272#else
1273
1274# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001275/* Note: this is only true for the `clone' system call, which handles
1276 arguments specially. We could as well say that its first two arguments
1277 are swapped relative to other architectures, but that would just be
1278 another #ifdef in the calls. */
1279# define arg0_offset PT_GPR3
1280# define arg1_offset PT_ORIGGPR2
1281# define restore_arg0(tcp, state, val) ((void) (state), 0)
1282# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001283# define arg0_index 1
1284# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001285# elif defined (ALPHA) || defined (MIPS)
1286# define arg0_offset REG_A0
1287# define arg1_offset (REG_A0+1)
1288# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001289# define arg0_offset (sizeof(unsigned long)*PT_R3)
1290# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001291# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001292# elif defined (HPPA)
1293# define arg0_offset PT_GR26
1294# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001295# elif defined (X86_64)
1296# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1297# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001298# elif defined (SH)
1299# define arg0_offset (4*(REG_REG0+4))
1300# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001301# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001302 /* ABI defines arg0 & 1 in r2 & r3 */
1303# define arg0_offset (REG_OFFSET+16)
1304# define arg1_offset (REG_OFFSET+24)
1305# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001306# else
1307# define arg0_offset 0
1308# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001309# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001310# define restore_arg0(tcp, state, val) 0
1311# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001312# endif
1313
1314typedef int arg_setup_state;
1315
1316# define arg_setup(tcp, state) (0)
1317# define arg_finish_change(tcp, state) 0
1318# define get_arg0(tcp, cookie, valp) \
1319 (upeek ((tcp)->pid, arg0_offset, (valp)))
1320# define get_arg1(tcp, cookie, valp) \
1321 (upeek ((tcp)->pid, arg1_offset, (valp)))
1322
1323static int
1324set_arg0 (struct tcb *tcp, void *cookie, long val)
1325{
1326 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1327}
1328
1329static int
1330set_arg1 (struct tcb *tcp, void *cookie, long val)
1331{
1332 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1333}
1334
1335#endif
1336
Roland McGrathe1df47f2003-01-14 09:46:15 +00001337#ifndef restore_arg0
1338# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1339#endif
1340#ifndef restore_arg1
1341# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1342#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001343
Roland McGrath90d0afd2004-03-01 21:05:16 +00001344#ifndef arg0_index
1345# define arg0_index 0
1346# define arg1_index 1
1347#endif
1348
Roland McGrathd81f1d92003-01-09 06:53:34 +00001349int
1350setbpt(tcp)
1351struct tcb *tcp;
1352{
1353 extern int change_syscall(struct tcb *, int);
1354 arg_setup_state state;
1355
1356 if (tcp->flags & TCB_BPTSET) {
1357 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1358 return -1;
1359 }
1360
1361 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001362#ifdef SYS_vfork
1363 case SYS_vfork:
1364#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001365#ifdef SYS_fork
1366 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001367#endif
1368#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001369 if (arg_setup (tcp, &state) < 0
1370 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1371 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1372 || change_syscall(tcp, SYS_clone) < 0
1373 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1374 || set_arg1 (tcp, &state, 0) < 0
1375 || arg_finish_change (tcp, &state) < 0)
1376 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001377 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1378 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001379 tcp->flags |= TCB_BPTSET;
1380 return 0;
1381#endif
1382
1383 case SYS_clone:
1384#ifdef SYS_clone2
1385 case SYS_clone2:
1386#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001387 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001388 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001389 || set_arg0 (tcp, &state,
1390 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001391 || arg_finish_change (tcp, &state) < 0))
1392 return -1;
1393 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001394 tcp->inst[0] = tcp->u_arg[arg0_index];
1395 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001396 return 0;
1397
1398 default:
1399 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1400 tcp->scno, tcp->pid);
1401 break;
1402 }
1403
1404 return -1;
1405}
1406
1407int
1408clearbpt(tcp)
1409struct tcb *tcp;
1410{
1411 arg_setup_state state;
1412 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001413 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1414 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001415 || arg_finish_change (tcp, &state))
1416 return -1;
1417 tcp->flags &= ~TCB_BPTSET;
1418 return 0;
1419}
1420
1421#else
1422
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423int
1424setbpt(tcp)
1425struct tcb *tcp;
1426{
1427
1428#ifdef LINUX
1429#ifdef SPARC
1430 /* We simply use the SunOS breakpoint code. */
1431
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001432 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433#define LOOPA 0x30800000 /* ba,a 0 */
1434
1435 if (tcp->flags & TCB_BPTSET) {
1436 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1437 return -1;
1438 }
1439 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1440 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1441 return -1;
1442 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001443 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444 errno = 0;
1445 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1446 if(errno) {
1447 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1448 return -1;
1449 }
1450
1451 /*
1452 * XXX - BRUTAL MODE ON
1453 * We cannot set a real BPT in the child, since it will not be
1454 * traced at the moment it will reach the trap and would probably
1455 * die with a core dump.
1456 * Thus, we are force our way in by taking out two instructions
1457 * and insert an eternal loop instead, in expectance of the SIGSTOP
1458 * generated by out PTRACE_ATTACH.
1459 * Of cause, if we evaporate ourselves in the middle of all this...
1460 */
1461 errno = 0;
1462 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1463 if(errno) {
1464 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1465 return -1;
1466 }
1467 tcp->flags |= TCB_BPTSET;
1468
1469#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001470#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001471 if (ia32) {
1472# define LOOP 0x0000feeb
1473 if (tcp->flags & TCB_BPTSET) {
1474 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1475 tcp->pid);
1476 return -1;
1477 }
1478 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1479 return -1;
1480 if (debug)
1481 fprintf(stderr, "[%d] setting bpt at %lx\n",
1482 tcp->pid, tcp->baddr);
1483 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1484 (char *) tcp->baddr, 0);
1485 if (errno) {
1486 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1487 return -1;
1488 }
1489 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1490 if (errno) {
1491 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1492 return -1;
1493 }
1494 tcp->flags |= TCB_BPTSET;
1495 } else {
1496 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001497 * Our strategy here is to replace the bundle that
1498 * contained the clone() syscall with a bundle of the
1499 * form:
1500 *
1501 * { 1: br 1b; br 1b; br 1b }
1502 *
1503 * This ensures that the newly forked child will loop
1504 * endlessly until we've got a chance to attach to it.
1505 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001506# define LOOP0 0x0000100000000017
1507# define LOOP1 0x4000000000200000
1508 unsigned long addr, ipsr;
1509 pid_t pid;
1510
1511 pid = tcp->pid;
1512 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1513 return -1;
1514 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1515 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001516 /* store "ri" in low two bits */
1517 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001518
1519 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001520 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1521 0);
1522 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1523 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001524 if (errno) {
1525 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1526 return -1;
1527 }
1528
1529 errno = 0;
1530 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1531 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1532 if (errno) {
1533 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1534 return -1;
1535 }
1536 tcp->flags |= TCB_BPTSET;
1537 }
1538#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539
Michal Ludvig0e035502002-09-23 15:41:01 +00001540#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541#define LOOP 0x0000feeb
1542#elif defined (M68K)
1543#define LOOP 0x60fe0000
1544#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001545#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001547#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001548#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001549#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001550#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001551#define LOOP 0x1000ffff
1552#elif defined(S390)
1553#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001554#elif defined(S390X)
1555#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001556#elif defined(HPPA)
1557#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001558#elif defined(SH)
1559#ifdef __LITTLE_ENDIAN__
1560#define LOOP 0x0000affe
1561#else
1562#define LOOP 0xfeaf0000
1563#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564#else
1565#error unknown architecture
1566#endif
1567
1568 if (tcp->flags & TCB_BPTSET) {
1569 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1570 return -1;
1571 }
1572#if defined (I386)
1573 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1574 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001575#elif defined (X86_64)
1576 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1577 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578#elif defined (M68K)
1579 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1580 return -1;
1581#elif defined (ALPHA)
1582 return -1;
1583#elif defined (ARM)
1584 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001585#elif defined (MIPS)
1586 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001588 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001590#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001591 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1592 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001593#elif defined(HPPA)
1594 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1595 return -1;
1596 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001597#elif defined(SH)
1598 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1599 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001600#else
1601#error unknown architecture
1602#endif
1603 if (debug)
1604 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1605 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1606 if (errno) {
1607 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1608 return -1;
1609 }
1610 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1611 if (errno) {
1612 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1613 return -1;
1614 }
1615 tcp->flags |= TCB_BPTSET;
1616
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001617#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001618#endif /* SPARC */
1619#endif /* LINUX */
1620
1621#ifdef SUNOS4
1622#ifdef SPARC /* This code is slightly sparc specific */
1623
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001624 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625#define BPT 0x91d02001 /* ta 1 */
1626#define LOOP 0x10800000 /* ba 0 */
1627#define LOOPA 0x30800000 /* ba,a 0 */
1628#define NOP 0x01000000
1629#if LOOPA
1630 static int loopdeloop[1] = {LOOPA};
1631#else
1632 static int loopdeloop[2] = {LOOP, NOP};
1633#endif
1634
1635 if (tcp->flags & TCB_BPTSET) {
1636 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1637 return -1;
1638 }
1639 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1640 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1641 return -1;
1642 }
1643 tcp->baddr = regs.r_o7 + 8;
1644 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1645 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1646 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1647 return -1;
1648 }
1649
1650 /*
1651 * XXX - BRUTAL MODE ON
1652 * We cannot set a real BPT in the child, since it will not be
1653 * traced at the moment it will reach the trap and would probably
1654 * die with a core dump.
1655 * Thus, we are force our way in by taking out two instructions
1656 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1657 * generated by out PTRACE_ATTACH.
1658 * Of cause, if we evaporate ourselves in the middle of all this...
1659 */
1660 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1661 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1662 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1663 return -1;
1664 }
1665 tcp->flags |= TCB_BPTSET;
1666
1667#endif /* SPARC */
1668#endif /* SUNOS4 */
1669
1670 return 0;
1671}
1672
1673int
1674clearbpt(tcp)
1675struct tcb *tcp;
1676{
1677
1678#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001679#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001681#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001682 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001683#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001685#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001686 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001687#elif defined(HPPA)
1688 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001689#elif defined(SH)
1690 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001691#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692
1693#ifdef SPARC
1694 /* Again, we borrow the SunOS breakpoint code. */
1695 if (!(tcp->flags & TCB_BPTSET)) {
1696 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1697 return -1;
1698 }
1699 errno = 0;
1700 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1701 if(errno) {
1702 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1703 return -1;
1704 }
1705 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001706#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001707 if (ia32) {
1708 unsigned long addr;
1709
1710 if (debug)
1711 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1712 if (!(tcp->flags & TCB_BPTSET)) {
1713 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1714 return -1;
1715 }
1716 errno = 0;
1717 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1718 if (errno) {
1719 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1720 return -1;
1721 }
1722 tcp->flags &= ~TCB_BPTSET;
1723
1724 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1725 return -1;
1726 if (addr != 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 addr, tcp->baddr);
1732 return 0;
1733 }
1734 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001735 unsigned long addr, ipsr;
1736 pid_t pid;
1737
1738 pid = tcp->pid;
1739
1740 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1741 return -1;
1742 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1743 return -1;
1744
1745 /* restore original bundle: */
1746 errno = 0;
1747 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1748 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1749 if (errno) {
1750 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1751 return -1;
1752 }
1753
1754 /* restore original "ri" in ipsr: */
1755 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1756 errno = 0;
1757 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1758 if (errno) {
1759 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1760 return -1;
1761 }
1762
1763 tcp->flags &= ~TCB_BPTSET;
1764
1765 if (addr != (tcp->baddr & ~0x3)) {
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 addr, tcp->baddr);
1770 return 0;
1771 }
1772 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001773#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774
1775 if (debug)
1776 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1777 if (!(tcp->flags & TCB_BPTSET)) {
1778 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1779 return -1;
1780 }
1781 errno = 0;
1782 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1783 if (errno) {
1784 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1785 return -1;
1786 }
1787 tcp->flags &= ~TCB_BPTSET;
1788
1789#ifdef I386
1790 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1791 return -1;
1792 if (eip != tcp->baddr) {
1793 /* The breakpoint has not been reached yet. */
1794 if (debug)
1795 fprintf(stderr,
1796 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1797 eip, tcp->baddr);
1798 return 0;
1799 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001800#elif defined(X86_64)
1801 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1802 return -1;
1803 if (eip != tcp->baddr) {
1804 /* The breakpoint has not been reached yet. */
1805 if (debug)
1806 fprintf(stderr,
1807 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1808 eip, tcp->baddr);
1809 return 0;
1810 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001811#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001812 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001813 return -1;
1814 if (pc != tcp->baddr) {
1815 /* The breakpoint has not been reached yet. */
1816 if (debug)
1817 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1818 pc, tcp->baddr);
1819 return 0;
1820 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001821#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1823 return -1;
1824 if (pc != tcp->baddr) {
1825 /* The breakpoint has not been reached yet. */
1826 if (debug)
1827 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1828 pc, tcp->baddr);
1829 return 0;
1830 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001831#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001832 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1833 return -1;
1834 if (pc != tcp->baddr) {
1835 /* The breakpoint has not been reached yet. */
1836 if (debug)
1837 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1838 pc, tcp->baddr);
1839 return 0;
1840 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001841#elif defined(HPPA)
1842 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1843 return -1;
1844 iaoq &= ~0x03;
1845 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1846 /* The breakpoint has not been reached yet. */
1847 if (debug)
1848 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1849 iaoq, tcp->baddr);
1850 return 0;
1851 }
1852 iaoq = tcp->baddr | 3;
1853 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1854 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1855 * has no significant effect.
1856 */
1857 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1858 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001859#elif defined(SH)
1860 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1861 return -1;
1862 if (pc != tcp->baddr) {
1863 /* The breakpoint has not been reached yet. */
1864 if (debug)
1865 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1866 pc, tcp->baddr);
1867 return 0;
1868 }
1869
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001870#endif /* arch */
1871#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001872#endif /* LINUX */
1873
1874#ifdef SUNOS4
1875#ifdef SPARC
1876
1877#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001878 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001879#endif
1880
1881 if (!(tcp->flags & TCB_BPTSET)) {
1882 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1883 return -1;
1884 }
1885 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1886 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1887 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1888 return -1;
1889 }
1890 tcp->flags &= ~TCB_BPTSET;
1891
1892#if !LOOPA
1893 /*
1894 * Since we don't have a single instruction breakpoint, we may have
1895 * to adjust the program counter after removing the our `breakpoint'.
1896 */
1897 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1898 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1899 return -1;
1900 }
1901 if ((regs.r_pc < tcp->baddr) ||
1902 (regs.r_pc > tcp->baddr + 4)) {
1903 /* The breakpoint has not been reached yet */
1904 if (debug)
1905 fprintf(stderr,
1906 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1907 regs.r_pc, tcp->parent->baddr);
1908 return 0;
1909 }
1910 if (regs.r_pc != tcp->baddr)
1911 if (debug)
1912 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1913 regs.r_pc, tcp->baddr);
1914
1915 regs.r_pc = tcp->baddr;
1916 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1917 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1918 return -1;
1919 }
1920#endif /* LOOPA */
1921#endif /* SPARC */
1922#endif /* SUNOS4 */
1923
1924 return 0;
1925}
1926
Roland McGrathd81f1d92003-01-09 06:53:34 +00001927#endif
1928
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001929#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001930
1931#ifdef SUNOS4
1932
1933static int
1934getex(pid, hdr)
1935int pid;
1936struct exec *hdr;
1937{
1938 int n;
1939
1940 for (n = 0; n < sizeof *hdr; n += 4) {
1941 long res;
1942 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1943 return -1;
1944 memcpy(((char *) hdr) + n, &res, 4);
1945 }
1946 if (debug) {
1947 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1948 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1949 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1950 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1951 }
1952 return 0;
1953}
1954
1955int
1956fixvfork(tcp)
1957struct tcb *tcp;
1958{
1959 int pid = tcp->pid;
1960 /*
1961 * Change `vfork' in a freshly exec'ed dynamically linked
1962 * executable's (internal) symbol table to plain old `fork'
1963 */
1964
1965 struct exec hdr;
1966 struct link_dynamic dyn;
1967 struct link_dynamic_2 ld;
1968 char *strtab, *cp;
1969
1970 if (getex(pid, &hdr) < 0)
1971 return -1;
1972 if (!hdr.a_dynamic)
1973 return -1;
1974
1975 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1976 fprintf(stderr, "Cannot read DYNAMIC\n");
1977 return -1;
1978 }
1979 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1980 fprintf(stderr, "Cannot read link_dynamic_2\n");
1981 return -1;
1982 }
1983 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1984 fprintf(stderr, "fixvfork: out of memory\n");
1985 return -1;
1986 }
1987 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1988 (int)ld.ld_symb_size, strtab) < 0)
1989 goto err;
1990
1991#if 0
1992 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1993 fprintf(stderr, "[symbol: %s]\n", cp);
1994 cp += strlen(cp)+1;
1995 }
1996 return 0;
1997#endif
1998 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1999 if (strcmp(cp, "_vfork") == 0) {
2000 if (debug)
2001 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2002 strcpy(cp, "_fork");
2003 break;
2004 }
2005 cp += strlen(cp)+1;
2006 }
2007 if (cp < strtab + ld.ld_symb_size)
2008 /*
2009 * Write entire symbol table back to avoid
2010 * memory alignment bugs in ptrace
2011 */
2012 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2013 (int)ld.ld_symb_size, strtab) < 0)
2014 goto err;
2015
2016 free(strtab);
2017 return 0;
2018
2019err:
2020 free(strtab);
2021 return -1;
2022}
2023
2024#endif /* SUNOS4 */