blob: 4b0a0616efab6ec7fa0309785f52e92c64a58371 [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
Roland McGrath6d1a65c2004-07-12 07:44:08 +000081#if defined(LINUXSPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
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
Roland McGrath6d1a65c2004-07-12 07:44:08 +000091#if defined (SPARC64)
92# define r_pc r_tpc
93# undef PTRACE_GETREGS
94# define PTRACE_GETREGS PTRACE_GETREGS64
95# undef PTRACE_SETREGS
96# define PTRACE_SETREGS PTRACE_SETREGS64
97#endif /* SPARC64 */
98
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000099#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100
101#include <linux/unistd.h>
102
103#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
106{ \
107 long __res; \
108\
109__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110 "or %%g0, %2, %%o1\n\t" \
111 "or %%g0, %3, %%o2\n\t" \
112 "or %%g0, %4, %%o3\n\t" \
113 "or %%g0, %5, %%o4\n\t" \
114 "or %%g0, %6, %%g1\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000115#if defined (SPARC64)
116 "t 0x6d\n\t" \
117#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118 "t 0x10\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000119#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 "bcc 1f\n\t" \
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
123 "1:\n\t" \
124 : "=r" (__res) \
125 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127 "i" (__NR_##syscall) \
128 : "g1", "o0", "o1", "o2", "o3", "o4"); \
129if (__res>=0) \
130 return (type) __res; \
131errno = -__res; \
132return -1; \
133}
134
135static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137#define _ptrace
138
139#endif
140
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000141#endif
142
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143/* macros */
144#ifndef MAX
145#define MAX(a,b) (((a) > (b)) ? (a) : (b))
146#endif
147#ifndef MIN
148#define MIN(a,b) (((a) < (b)) ? (a) : (b))
149#endif
150
Roland McGratha4d48532005-06-08 20:45:28 +0000151#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152void
153tv_tv(tv, a, b)
154struct timeval *tv;
155int a;
156int b;
157{
158 tv->tv_sec = a;
159 tv->tv_usec = b;
160}
Roland McGratha4d48532005-06-08 20:45:28 +0000161#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162
163int
164tv_nz(a)
165struct timeval *a;
166{
167 return a->tv_sec || a->tv_usec;
168}
169
170int
171tv_cmp(a, b)
172struct timeval *a, *b;
173{
174 if (a->tv_sec < b->tv_sec
175 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
176 return -1;
177 if (a->tv_sec > b->tv_sec
178 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
179 return 1;
180 return 0;
181}
182
183double
184tv_float(tv)
185struct timeval *tv;
186{
187 return tv->tv_sec + tv->tv_usec/1000000.0;
188}
189
190void
191tv_add(tv, a, b)
192struct timeval *tv, *a, *b;
193{
194 tv->tv_sec = a->tv_sec + b->tv_sec;
195 tv->tv_usec = a->tv_usec + b->tv_usec;
196 if (tv->tv_usec > 1000000) {
197 tv->tv_sec++;
198 tv->tv_usec -= 1000000;
199 }
200}
201
202void
203tv_sub(tv, a, b)
204struct timeval *tv, *a, *b;
205{
206 tv->tv_sec = a->tv_sec - b->tv_sec;
207 tv->tv_usec = a->tv_usec - b->tv_usec;
208 if (((long) tv->tv_usec) < 0) {
209 tv->tv_sec--;
210 tv->tv_usec += 1000000;
211 }
212}
213
214void
215tv_div(tv, a, n)
216struct timeval *tv, *a;
217int n;
218{
219 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
220 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
221 tv->tv_usec %= 1000000;
222}
223
224void
225tv_mul(tv, a, n)
226struct timeval *tv, *a;
227int n;
228{
229 tv->tv_usec = a->tv_usec * n;
230 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
231 tv->tv_usec %= 1000000;
232}
233
234char *
235xlookup(xlat, val)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000236const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237int val;
238{
239 for (; xlat->str != NULL; xlat++)
240 if (xlat->val == val)
241 return xlat->str;
242 return NULL;
243}
244
245/*
246 * Print entry in struct xlat table, if there.
247 */
248void
249printxval(xlat, val, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000250const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251int val;
Roland McGrathb2dee132005-06-01 19:02:36 +0000252const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000253{
254 char *str = xlookup(xlat, val);
255
256 if (str)
257 tprintf("%s", str);
258 else
259 tprintf("%#x /* %s */", val, dflt);
260}
261
262/*
263 * Interpret `xlat' as an array of flags
264 * print the entries whose bits are on in `flags'
265 * return # of flags printed.
266 */
267int
268addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000269const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000270int flags;
271{
272 int n;
273
274 for (n = 0; xlat->str; xlat++) {
275 if (xlat->val && (flags & xlat->val) == xlat->val) {
276 tprintf("|%s", xlat->str);
277 flags &= ~xlat->val;
278 n++;
279 }
280 }
281 if (flags) {
282 tprintf("|%#x", flags);
283 n++;
284 }
285 return n;
286}
287
288int
Roland McGrathb2dee132005-06-01 19:02:36 +0000289printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000290const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000291int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000292const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000293{
294 int n;
295 char *sep;
296
297 if (flags == 0 && xlat->val == 0) {
298 tprintf("%s", xlat->str);
299 return 1;
300 }
301
302 sep = "";
303 for (n = 0; xlat->str; xlat++) {
304 if (xlat->val && (flags & xlat->val) == xlat->val) {
305 tprintf("%s%s", sep, xlat->str);
306 flags &= ~xlat->val;
307 sep = "|";
308 n++;
309 }
310 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000311
312 if (n) {
313 if (flags) {
314 tprintf("%s%#x", sep, flags);
315 n++;
316 }
317 } else {
318 if (flags) {
319 tprintf("%#x", flags);
320 if (dflt)
321 tprintf(" /* %s */", dflt);
322 } else {
323 if (dflt)
324 tprintf("0");
325 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000327
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328 return n;
329}
330
331void
332printnum(tcp, addr, fmt)
333struct tcb *tcp;
334long addr;
335char *fmt;
336{
Roland McGratheb285352003-01-14 09:59:00 +0000337 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000338
339 if (!addr) {
340 tprintf("NULL");
341 return;
342 }
343 if (umove(tcp, addr, &num) < 0) {
344 tprintf("%#lx", addr);
345 return;
346 }
347 tprintf("[");
348 tprintf(fmt, num);
349 tprintf("]");
350}
351
Roland McGrath6bc12202003-11-13 22:32:27 +0000352void
Roland McGrath9814a942005-07-04 23:28:10 +0000353printnum_int(tcp, addr, fmt)
354struct tcb *tcp;
355long addr;
356char *fmt;
357{
358 int num;
359
360 if (!addr) {
361 tprintf("NULL");
362 return;
363 }
364 if (umove(tcp, addr, &num) < 0) {
365 tprintf("%#lx", addr);
366 return;
367 }
368 tprintf("[");
369 tprintf(fmt, num);
370 tprintf("]");
371}
372
373void
Roland McGrath6bc12202003-11-13 22:32:27 +0000374printuid(text, uid)
375const char *text;
376unsigned long uid;
377{
378 tprintf("%s", text);
379 tprintf((uid == -1) ? "%ld" : "%lu", uid);
380}
381
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382static char path[MAXPATHLEN + 1];
383
Roland McGratha4d48532005-06-08 20:45:28 +0000384static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385string_quote(str)
Roland McGratha4d48532005-06-08 20:45:28 +0000386const char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387{
388 char buf[2 * MAXPATHLEN + 1];
389 char *s;
390
391 if (!strpbrk(str, "\"\'\\")) {
392 tprintf("\"%s\"", str);
393 return;
394 }
395 for (s = buf; *str; str++) {
396 switch (*str) {
397 case '\"': case '\'': case '\\':
398 *s++ = '\\'; *s++ = *str; break;
399 default:
400 *s++ = *str; break;
401 }
402 }
403 *s = '\0';
404 tprintf("\"%s\"", buf);
405}
406
407void
408printpath(tcp, addr)
409struct tcb *tcp;
410long addr;
411{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000412 if (addr == 0)
413 tprintf("NULL");
414 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000415 tprintf("%#lx", addr);
416 else
417 string_quote(path);
418 return;
419}
420
421void
422printpathn(tcp, addr, n)
423struct tcb *tcp;
424long addr;
425int n;
426{
Roland McGrathb15c4e42005-10-21 22:06:46 +0000427 if (n >= sizeof path)
428 n = sizeof path - 1;
429
Roland McGrath371ed8f2005-02-06 01:55:07 +0000430 if (addr == 0)
431 tprintf("NULL");
432 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433 tprintf("%#lx", addr);
434 else {
435 path[n] = '\0';
436 string_quote(path);
437 }
438}
439
440void
441printstr(tcp, addr, len)
442struct tcb *tcp;
443long addr;
444int len;
445{
446 static unsigned char *str = NULL;
447 static char *outstr;
448 int i, n, c, usehex;
449 char *s, *outend;
450
451 if (!addr) {
452 tprintf("NULL");
453 return;
454 }
455 if (!str) {
456 if ((str = malloc(max_strlen)) == NULL
457 || (outstr = malloc(2*max_strlen)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000458 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000459 tprintf("%#lx", addr);
460 return;
461 }
462 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000463 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000464 if (len < 0) {
465 n = max_strlen;
466 if (umovestr(tcp, addr, n, (char *) str) < 0) {
467 tprintf("%#lx", addr);
468 return;
469 }
470 }
471 else {
472 n = MIN(len, max_strlen);
473 if (umoven(tcp, addr, n, (char *) str) < 0) {
474 tprintf("%#lx", addr);
475 return;
476 }
477 }
478
479 usehex = 0;
480 if (xflag > 1)
481 usehex = 1;
482 else if (xflag) {
483 for (i = 0; i < n; i++) {
484 c = str[i];
485 if (len < 0 && c == '\0')
486 break;
487 if (!isprint(c) && !isspace(c)) {
488 usehex = 1;
489 break;
490 }
491 }
492 }
493
494 s = outstr;
495 *s++ = '\"';
496
497 if (usehex) {
498 for (i = 0; i < n; i++) {
499 c = str[i];
500 if (len < 0 && c == '\0')
501 break;
502 sprintf(s, "\\x%02x", c);
503 s += 4;
504 if (s > outend)
505 break;
506 }
507 }
508 else {
509 for (i = 0; i < n; i++) {
510 c = str[i];
511 if (len < 0 && c == '\0')
512 break;
513 switch (c) {
514 case '\"': case '\'': case '\\':
515 *s++ = '\\'; *s++ = c; break;
516 case '\f':
517 *s++ = '\\'; *s++ = 'f'; break;
518 case '\n':
519 *s++ = '\\'; *s++ = 'n'; break;
520 case '\r':
521 *s++ = '\\'; *s++ = 'r'; break;
522 case '\t':
523 *s++ = '\\'; *s++ = 't'; break;
524 case '\v':
525 *s++ = '\\'; *s++ = 'v'; break;
526 default:
527 if (isprint(c))
528 *s++ = c;
529 else if (i < n - 1 && isdigit(str[i + 1])) {
530 sprintf(s, "\\%03o", c);
531 s += 4;
532 }
533 else {
534 sprintf(s, "\\%o", c);
535 s += strlen(s);
536 }
537 break;
538 }
539 if (s > outend)
540 break;
541 }
542 }
543
544 *s++ = '\"';
545 if (i < len || (len < 0 && (i == n || s > outend))) {
546 *s++ = '.'; *s++ = '.'; *s++ = '.';
547 }
548 *s = '\0';
549 tprintf("%s", outstr);
550}
551
John Hughes1d08dcf2001-07-10 13:48:44 +0000552#if HAVE_SYS_UIO_H
553void
554dumpiov(tcp, len, addr)
555struct tcb * tcp;
556int len;
557long addr;
558{
559 struct iovec *iov;
560 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000561 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000562
Roland McGrathaa524c82005-06-01 19:22:06 +0000563 size = sizeof(*iov) * (unsigned long) len;
564 if (size / sizeof(*iov) != len
565 || (iov = (struct iovec *) malloc(size)) == NULL) {
566 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000567 return;
568 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000569 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000570 for (i = 0; i < len; i++) {
571 /* include the buffer number to make it easy to
572 * match up the trace with the source */
573 tprintf(" * %lu bytes in buffer %d\n",
574 (unsigned long)iov[i].iov_len, i);
575 dumpstr(tcp, (long) iov[i].iov_base,
576 iov[i].iov_len);
577 }
578 }
579 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000580
John Hughes1d08dcf2001-07-10 13:48:44 +0000581}
582#endif
583
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584void
585dumpstr(tcp, addr, len)
586struct tcb *tcp;
587long addr;
588int len;
589{
590 static int strsize = -1;
591 static unsigned char *str;
592 static char outstr[80];
593 char *s;
594 int i, j;
595
596 if (strsize < len) {
597 if (str)
598 free(str);
599 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000600 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000601 return;
602 }
603 strsize = len;
604 }
605
606 if (umoven(tcp, addr, len, (char *) str) < 0)
607 return;
608
609 for (i = 0; i < len; i += 16) {
610 s = outstr;
611 sprintf(s, " | %05x ", i);
612 s += 9;
613 for (j = 0; j < 16; j++) {
614 if (j == 8)
615 *s++ = ' ';
616 if (i + j < len) {
617 sprintf(s, " %02x", str[i + j]);
618 s += 3;
619 }
620 else {
621 *s++ = ' '; *s++ = ' '; *s++ = ' ';
622 }
623 }
624 *s++ = ' '; *s++ = ' ';
625 for (j = 0; j < 16; j++) {
626 if (j == 8)
627 *s++ = ' ';
628 if (i + j < len) {
629 if (isprint(str[i + j]))
630 *s++ = str[i + j];
631 else
632 *s++ = '.';
633 }
634 else
635 *s++ = ' ';
636 }
637 tprintf("%s |\n", outstr);
638 }
639}
640
641#define PAGMASK (~(PAGSIZ - 1))
642/*
643 * move `len' bytes of data from process `pid'
644 * at address `addr' to our space at `laddr'
645 */
646int
647umoven(tcp, addr, len, laddr)
648struct tcb *tcp;
649long addr;
650int len;
651char *laddr;
652{
653
654#ifdef LINUX
655 int pid = tcp->pid;
656 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000657 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000658 union {
659 long val;
660 char x[sizeof(long)];
661 } u;
662
663 if (addr & (sizeof(long) - 1)) {
664 /* addr not a multiple of sizeof(long) */
665 n = addr - (addr & -sizeof(long)); /* residue */
666 addr &= -sizeof(long); /* residue */
667 errno = 0;
668 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
669 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000670 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000671 /* Ran into 'end of memory' - stupid "printpath" */
672 return 0;
673 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000674 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000675 perror("ptrace: umoven");
676 return -1;
677 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000678 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000679 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
680 addr += sizeof(long), laddr += m, len -= m;
681 }
682 while (len) {
683 errno = 0;
684 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
685 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000686 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000687 /* Ran into 'end of memory' - stupid "printpath" */
688 return 0;
689 }
Roland McGrath4db26242003-01-30 20:15:19 +0000690 if (addr != 0)
691 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692 return -1;
693 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000694 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
696 addr += sizeof(long), laddr += m, len -= m;
697 }
698#endif /* LINUX */
699
700#ifdef SUNOS4
701 int pid = tcp->pid;
702#if 0
703 int n, m;
704 union {
705 long val;
706 char x[sizeof(long)];
707 } u;
708
709 if (addr & (sizeof(long) - 1)) {
710 /* addr not a multiple of sizeof(long) */
711 n = addr - (addr & -sizeof(long)); /* residue */
712 addr &= -sizeof(long); /* residue */
713 errno = 0;
714 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
715 if (errno) {
716 perror("umoven");
717 return -1;
718 }
719 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
720 addr += sizeof(long), laddr += m, len -= m;
721 }
722 while (len) {
723 errno = 0;
724 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
725 if (errno) {
726 perror("umoven");
727 return -1;
728 }
729 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
730 addr += sizeof(long), laddr += m, len -= m;
731 }
732#else /* !oldway */
733 int n;
734
735 while (len) {
736 n = MIN(len, PAGSIZ);
737 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
738 if (ptrace(PTRACE_READDATA, pid,
739 (char *) addr, len, laddr) < 0) {
740 perror("umoven: ptrace(PTRACE_READDATA, ...)");
741 abort();
742 return -1;
743 }
744 len -= n;
745 addr += n;
746 laddr += n;
747 }
748#endif /* !oldway */
749#endif /* SUNOS4 */
750
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000751#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000752#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000753 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000754#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000755 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000757 lseek(fd, addr, SEEK_SET);
758 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000759 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000760#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000761
762 return 0;
763}
764
765/*
766 * like `umove' but make the additional effort of looking
767 * for a terminating zero byte.
768 */
769int
770umovestr(tcp, addr, len, laddr)
771struct tcb *tcp;
772long addr;
773int len;
774char *laddr;
775{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000776#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000777#ifdef HAVE_MP_PROCFS
778 int fd = tcp->pfd_as;
779#else
780 int fd = tcp->pfd;
781#endif
782 /* Some systems (e.g. FreeBSD) can be upset if we read off the
783 end of valid memory, avoid this by trying to read up
784 to page boundaries. But we don't know what a page is (and
785 getpagesize(2) (if it exists) doesn't necessarily return
786 hardware page size). Assume all pages >= 1024 (a-historical
787 I know) */
788
789 int page = 1024; /* How to find this? */
790 int move = page - (addr & (page - 1));
791 int left = len;
792
793 lseek(fd, addr, SEEK_SET);
794
795 while (left) {
796 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000797 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000798 return left != len ? 0 : -1;
799 if (memchr (laddr, 0, move)) break;
800 left -= move;
801 laddr += move;
802 addr += move;
803 move = page;
804 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000805#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000806 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000807 int pid = tcp->pid;
808 int i, n, m;
809 union {
810 long val;
811 char x[sizeof(long)];
812 } u;
813
814 if (addr & (sizeof(long) - 1)) {
815 /* addr not a multiple of sizeof(long) */
816 n = addr - (addr & -sizeof(long)); /* residue */
817 addr &= -sizeof(long); /* residue */
818 errno = 0;
819 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
820 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000821 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000822 /* Ran into 'end of memory' - stupid "printpath" */
823 return 0;
824 }
825 perror("umovestr");
826 return -1;
827 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000828 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000829 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
830 while (n & (sizeof(long) - 1))
831 if (u.x[n++] == '\0')
832 return 0;
833 addr += sizeof(long), laddr += m, len -= m;
834 }
835 while (len) {
836 errno = 0;
837 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
838 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000839 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840 /* Ran into 'end of memory' - stupid "printpath" */
841 return 0;
842 }
843 perror("umovestr");
844 return -1;
845 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000846 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
848 for (i = 0; i < sizeof(long); i++)
849 if (u.x[i] == '\0')
850 return 0;
851
852 addr += sizeof(long), laddr += m, len -= m;
853 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000854#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000855 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000856}
857
858#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000859#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000860#define PTRACE_WRITETEXT 101
861#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000862#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000863#endif /* LINUX */
864
865#ifdef SUNOS4
866
867static int
868uload(cmd, pid, addr, len, laddr)
869int cmd;
870int pid;
871long addr;
872int len;
873char *laddr;
874{
875#if 0
876 int n;
877
878 while (len) {
879 n = MIN(len, PAGSIZ);
880 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
881 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
882 perror("uload: ptrace(PTRACE_WRITE, ...)");
883 return -1;
884 }
885 len -= n;
886 addr += n;
887 laddr += n;
888 }
889#else
890 int peek, poke;
891 int n, m;
892 union {
893 long val;
894 char x[sizeof(long)];
895 } u;
896
897 if (cmd == PTRACE_WRITETEXT) {
898 peek = PTRACE_PEEKTEXT;
899 poke = PTRACE_POKETEXT;
900 }
901 else {
902 peek = PTRACE_PEEKDATA;
903 poke = PTRACE_POKEDATA;
904 }
905 if (addr & (sizeof(long) - 1)) {
906 /* addr not a multiple of sizeof(long) */
907 n = addr - (addr & -sizeof(long)); /* residue */
908 addr &= -sizeof(long);
909 errno = 0;
910 u.val = ptrace(peek, pid, (char *) addr, 0);
911 if (errno) {
912 perror("uload: POKE");
913 return -1;
914 }
915 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
916 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
917 perror("uload: POKE");
918 return -1;
919 }
920 addr += sizeof(long), laddr += m, len -= m;
921 }
922 while (len) {
923 if (len < sizeof(long))
924 u.val = ptrace(peek, pid, (char *) addr, 0);
925 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
926 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
927 perror("uload: POKE");
928 return -1;
929 }
930 addr += sizeof(long), laddr += m, len -= m;
931 }
932#endif
933 return 0;
934}
935
936int
937tload(pid, addr, len, laddr)
938int pid;
939int addr, len;
940char *laddr;
941{
942 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
943}
944
945int
946dload(pid, addr, len, laddr)
947int pid;
948int addr;
949int len;
950char *laddr;
951{
952 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
953}
954
955#endif /* SUNOS4 */
956
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000957#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958
959int
960upeek(pid, off, res)
961int pid;
962long off;
963long *res;
964{
965 long val;
966
967#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
968 {
969 static int is_sun4m = -1;
970 struct utsname name;
971
972 /* Round up the usual suspects. */
973 if (is_sun4m == -1) {
974 if (uname(&name) < 0) {
975 perror("upeek: uname?");
976 exit(1);
977 }
978 is_sun4m = strcmp(name.machine, "sun4m") == 0;
979 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000980 extern const struct xlat struct_user_offsets[];
981 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982
983 for (x = struct_user_offsets; x->str; x++)
984 x->val += 1024;
985 }
986 }
987 if (is_sun4m)
988 off += 1024;
989 }
990#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
991 errno = 0;
992 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
993 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000994 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000995 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000996 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997 return -1;
998 }
999 *res = val;
1000 return 0;
1001}
1002
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001003#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004
Roland McGratha4d48532005-06-08 20:45:28 +00001005#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006long
1007getpc(tcp)
1008struct tcb *tcp;
1009{
1010
1011#ifdef LINUX
1012 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001013#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1015 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001016#elif defined(X86_64)
1017 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1018 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001019#elif defined(IA64)
1020 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1021 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001022#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001023 if (upeek(tcp->pid, 4*15, &pc) < 0)
1024 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001025#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001026 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001028#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1030 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001031#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1033 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001034#elif defined(MIPS)
1035 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1036 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001037#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001038 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1040 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001041 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001042#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001043 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001044 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001045#elif defined(HPPA)
1046 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1047 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001048#elif defined(SH)
1049 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1050 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001051#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001052 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1053 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001054#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 return pc;
1056#endif /* LINUX */
1057
1058#ifdef SUNOS4
1059 /*
1060 * Return current program counter for `pid'
1061 * Assumes PC is never 0xffffffff
1062 */
1063 struct regs regs;
1064
1065 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1066 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1067 return -1;
1068 }
1069 return regs.r_pc;
1070#endif /* SUNOS4 */
1071
1072#ifdef SVR4
1073 /* XXX */
1074 return 0;
1075#endif /* SVR4 */
1076
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001077#ifdef FREEBSD
1078 struct reg regs;
1079 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1080 return regs.r_eip;
1081#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082}
Roland McGratha4d48532005-06-08 20:45:28 +00001083#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084
1085void
1086printcall(tcp)
1087struct tcb *tcp;
1088{
Roland McGrath7a918832005-02-02 20:55:23 +00001089#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1090 sizeof(long) == 8 ? "[????????????????] " : \
1091 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092
1093#ifdef LINUX
1094#ifdef I386
1095 long eip;
1096
1097 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001098 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 return;
1100 }
1101 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001102
1103#elif defined(S390) || defined(S390X)
1104 long psw;
1105 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001106 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001107 return;
1108 }
1109#ifdef S390
1110 tprintf("[%08lx] ", psw);
1111#elif S390X
1112 tprintf("[%16lx] ", psw);
1113#endif
1114
Michal Ludvig0e035502002-09-23 15:41:01 +00001115#elif defined(X86_64)
1116 long rip;
1117
1118 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001119 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001120 return;
1121 }
1122 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001123#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001124 long ip;
1125
1126 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001127 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001128 return;
1129 }
1130 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001131#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 long pc;
1133
Roland McGratheb285352003-01-14 09:59:00 +00001134 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 tprintf ("[????????] ");
1136 return;
1137 }
1138 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001139#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140 long pc;
1141
1142 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1143 tprintf ("[????????] ");
1144 return;
1145 }
1146 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001147#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 long pc;
1149
1150 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001151 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152 return;
1153 }
1154 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001155#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001156 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001158 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 return;
1160 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001161 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001162#elif defined(HPPA)
1163 long pc;
1164
1165 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1166 tprintf ("[????????] ");
1167 return;
1168 }
1169 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001170#elif defined(MIPS)
1171 long pc;
1172
1173 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1174 tprintf ("[????????] ");
1175 return;
1176 }
1177 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001178#elif defined(SH)
1179 long pc;
1180
1181 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1182 tprintf ("[????????] ");
1183 return;
1184 }
1185 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001186#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001187 long pc;
1188
1189 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001190 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001191 return;
1192 }
1193 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001194#elif defined(ARM)
1195 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001196
Roland McGrathef388682003-06-03 23:28:59 +00001197 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001198 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001199 return;
1200 }
1201 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001202#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001203#endif /* LINUX */
1204
1205#ifdef SUNOS4
1206 struct regs regs;
1207
1208 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1209 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001210 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 return;
1212 }
1213 tprintf("[%08x] ", regs.r_o7);
1214#endif /* SUNOS4 */
1215
1216#ifdef SVR4
1217 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001218 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219#endif
1220
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001221#ifdef FREEBSD
1222 struct reg regs;
1223 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1224 tprintf("[%08x] ", regs.r_eip);
1225#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226}
1227
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001228#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229
Roland McGrathd81f1d92003-01-09 06:53:34 +00001230#if defined LINUX
1231
1232#include <sys/syscall.h>
1233#ifndef CLONE_PTRACE
1234# define CLONE_PTRACE 0x00002000
1235#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001236#ifndef CLONE_STOPPED
1237# define CLONE_STOPPED 0x02000000
1238#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001239
1240#ifdef IA64
1241
Roland McGrath08267b82004-02-20 22:56:43 +00001242/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1243 subsystem has them for x86... */
1244#define SYS_fork 2
1245#define SYS_vfork 190
1246
Roland McGrathd81f1d92003-01-09 06:53:34 +00001247typedef unsigned long *arg_setup_state;
1248
1249static int
1250arg_setup(struct tcb *tcp, arg_setup_state *state)
1251{
1252 unsigned long *bsp, cfm, sof, sol;
1253
Roland McGrath08267b82004-02-20 22:56:43 +00001254 if (ia32)
1255 return 0;
1256
Roland McGrathd81f1d92003-01-09 06:53:34 +00001257 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1258 return -1;
1259 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1260 return -1;
1261
1262 sof = (cfm >> 0) & 0x7f;
1263 sol = (cfm >> 7) & 0x7f;
1264 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1265
1266 *state = bsp;
1267 return 0;
1268}
1269
1270# define arg_finish_change(tcp, state) 0
1271
1272#ifdef SYS_fork
1273static int
1274get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1275{
Roland McGrath08267b82004-02-20 22:56:43 +00001276 int ret;
1277
1278 if (ia32)
1279 ret = upeek (tcp->pid, PT_R11, valp);
1280 else
1281 ret = umoven (tcp,
1282 (unsigned long) ia64_rse_skip_regs(*state, 0),
1283 sizeof(long), (void *) valp);
1284 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001285}
1286
1287static int
1288get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1289{
Roland McGrath08267b82004-02-20 22:56:43 +00001290 int ret;
1291
1292 if (ia32)
1293 ret = upeek (tcp->pid, PT_R9, valp);
1294 else
1295 ret = umoven (tcp,
1296 (unsigned long) ia64_rse_skip_regs(*state, 1),
1297 sizeof(long), (void *) valp);
1298 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001299}
1300#endif
1301
1302static int
1303set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1304{
Roland McGrath08267b82004-02-20 22:56:43 +00001305 int req = PTRACE_POKEDATA;
1306 void *ap;
1307
1308 if (ia32) {
1309 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1310 req = PTRACE_POKEUSER;
1311 } else
1312 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001313 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001314 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001315 return errno ? -1 : 0;
1316}
1317
1318static int
1319set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1320{
Roland McGrath08267b82004-02-20 22:56:43 +00001321 int req = PTRACE_POKEDATA;
1322 void *ap;
1323
1324 if (ia32) {
1325 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1326 req = PTRACE_POKEUSER;
1327 } else
1328 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001329 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001330 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001331 return errno ? -1 : 0;
1332}
1333
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001334#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001335
1336typedef struct regs arg_setup_state;
1337
1338# define arg_setup(tcp, state) \
1339 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1340# define arg_finish_change(tcp, state) \
1341 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1342
1343# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1344# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1345# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1346# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001347# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001348
1349#else
1350
1351# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001352/* Note: this is only true for the `clone' system call, which handles
1353 arguments specially. We could as well say that its first two arguments
1354 are swapped relative to other architectures, but that would just be
1355 another #ifdef in the calls. */
1356# define arg0_offset PT_GPR3
1357# define arg1_offset PT_ORIGGPR2
1358# define restore_arg0(tcp, state, val) ((void) (state), 0)
1359# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001360# define arg0_index 1
1361# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001362# elif defined (ALPHA) || defined (MIPS)
1363# define arg0_offset REG_A0
1364# define arg1_offset (REG_A0+1)
1365# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001366# define arg0_offset (sizeof(unsigned long)*PT_R3)
1367# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001368# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001369# elif defined (HPPA)
1370# define arg0_offset PT_GR26
1371# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001372# elif defined (X86_64)
1373# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1374# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001375# elif defined (SH)
1376# define arg0_offset (4*(REG_REG0+4))
1377# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001378# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001379 /* ABI defines arg0 & 1 in r2 & r3 */
1380# define arg0_offset (REG_OFFSET+16)
1381# define arg1_offset (REG_OFFSET+24)
1382# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001383# else
1384# define arg0_offset 0
1385# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001386# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001387# define restore_arg0(tcp, state, val) 0
1388# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001389# endif
1390
1391typedef int arg_setup_state;
1392
1393# define arg_setup(tcp, state) (0)
1394# define arg_finish_change(tcp, state) 0
1395# define get_arg0(tcp, cookie, valp) \
1396 (upeek ((tcp)->pid, arg0_offset, (valp)))
1397# define get_arg1(tcp, cookie, valp) \
1398 (upeek ((tcp)->pid, arg1_offset, (valp)))
1399
1400static int
1401set_arg0 (struct tcb *tcp, void *cookie, long val)
1402{
Roland McGrathca85b972005-06-07 23:22:08 +00001403 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001404}
1405
1406static int
1407set_arg1 (struct tcb *tcp, void *cookie, long val)
1408{
1409 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1410}
1411
1412#endif
1413
Roland McGrathe1df47f2003-01-14 09:46:15 +00001414#ifndef restore_arg0
1415# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1416#endif
1417#ifndef restore_arg1
1418# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1419#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001420
Roland McGrath90d0afd2004-03-01 21:05:16 +00001421#ifndef arg0_index
1422# define arg0_index 0
1423# define arg1_index 1
1424#endif
1425
Roland McGrathd81f1d92003-01-09 06:53:34 +00001426int
1427setbpt(tcp)
1428struct tcb *tcp;
1429{
1430 extern int change_syscall(struct tcb *, int);
1431 arg_setup_state state;
1432
1433 if (tcp->flags & TCB_BPTSET) {
1434 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1435 return -1;
1436 }
1437
Roland McGrath76989d72005-06-07 23:21:31 +00001438 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001439#ifdef SYS_vfork
1440 case SYS_vfork:
1441#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001442#ifdef SYS_fork
1443 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001444#endif
1445#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001446 if (arg_setup (tcp, &state) < 0
1447 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1448 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1449 || change_syscall(tcp, SYS_clone) < 0
1450 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1451 || set_arg1 (tcp, &state, 0) < 0
1452 || arg_finish_change (tcp, &state) < 0)
1453 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001454 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1455 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001456 tcp->flags |= TCB_BPTSET;
1457 return 0;
1458#endif
1459
1460 case SYS_clone:
1461#ifdef SYS_clone2
1462 case SYS_clone2:
1463#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001464 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001465 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001466 || set_arg0 (tcp, &state,
1467 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001468 || arg_finish_change (tcp, &state) < 0))
1469 return -1;
1470 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001471 tcp->inst[0] = tcp->u_arg[arg0_index];
1472 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001473 return 0;
1474
1475 default:
1476 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1477 tcp->scno, tcp->pid);
1478 break;
1479 }
1480
1481 return -1;
1482}
1483
1484int
1485clearbpt(tcp)
1486struct tcb *tcp;
1487{
1488 arg_setup_state state;
1489 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001490 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1491 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001492 || arg_finish_change (tcp, &state))
1493 return -1;
1494 tcp->flags &= ~TCB_BPTSET;
1495 return 0;
1496}
1497
1498#else
1499
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500int
1501setbpt(tcp)
1502struct tcb *tcp;
1503{
1504
1505#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001506#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507 /* We simply use the SunOS breakpoint code. */
1508
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001509 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001510 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001511#define LOOPA 0x30800000 /* ba,a 0 */
1512
1513 if (tcp->flags & TCB_BPTSET) {
1514 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1515 return -1;
1516 }
1517 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1518 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1519 return -1;
1520 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001521 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522 errno = 0;
1523 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1524 if(errno) {
1525 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1526 return -1;
1527 }
1528
1529 /*
1530 * XXX - BRUTAL MODE ON
1531 * We cannot set a real BPT in the child, since it will not be
1532 * traced at the moment it will reach the trap and would probably
1533 * die with a core dump.
1534 * Thus, we are force our way in by taking out two instructions
1535 * and insert an eternal loop instead, in expectance of the SIGSTOP
1536 * generated by out PTRACE_ATTACH.
1537 * Of cause, if we evaporate ourselves in the middle of all this...
1538 */
1539 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001540 inst = LOOPA;
1541#if defined (SPARC64)
1542 inst <<= 32;
1543 inst |= (tcp->inst[0] & 0xffffffffUL);
1544#endif
1545 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546 if(errno) {
1547 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1548 return -1;
1549 }
1550 tcp->flags |= TCB_BPTSET;
1551
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001552#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001553#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001554 if (ia32) {
1555# define LOOP 0x0000feeb
1556 if (tcp->flags & TCB_BPTSET) {
1557 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1558 tcp->pid);
1559 return -1;
1560 }
1561 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1562 return -1;
1563 if (debug)
1564 fprintf(stderr, "[%d] setting bpt at %lx\n",
1565 tcp->pid, tcp->baddr);
1566 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1567 (char *) tcp->baddr, 0);
1568 if (errno) {
1569 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1570 return -1;
1571 }
1572 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1573 if (errno) {
1574 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1575 return -1;
1576 }
1577 tcp->flags |= TCB_BPTSET;
1578 } else {
1579 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001580 * Our strategy here is to replace the bundle that
1581 * contained the clone() syscall with a bundle of the
1582 * form:
1583 *
1584 * { 1: br 1b; br 1b; br 1b }
1585 *
1586 * This ensures that the newly forked child will loop
1587 * endlessly until we've got a chance to attach to it.
1588 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001589# define LOOP0 0x0000100000000017
1590# define LOOP1 0x4000000000200000
1591 unsigned long addr, ipsr;
1592 pid_t pid;
1593
1594 pid = tcp->pid;
1595 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1596 return -1;
1597 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1598 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001599 /* store "ri" in low two bits */
1600 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001601
1602 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001603 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1604 0);
1605 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1606 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001607 if (errno) {
1608 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1609 return -1;
1610 }
1611
1612 errno = 0;
1613 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1614 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1615 if (errno) {
1616 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1617 return -1;
1618 }
1619 tcp->flags |= TCB_BPTSET;
1620 }
1621#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622
Michal Ludvig0e035502002-09-23 15:41:01 +00001623#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001624#define LOOP 0x0000feeb
1625#elif defined (M68K)
1626#define LOOP 0x60fe0000
1627#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001628#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001629#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001630#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001632#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001633#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001634#define LOOP 0x1000ffff
1635#elif defined(S390)
1636#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001637#elif defined(S390X)
1638#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001639#elif defined(HPPA)
1640#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001641#elif defined(SH)
1642#ifdef __LITTLE_ENDIAN__
1643#define LOOP 0x0000affe
1644#else
1645#define LOOP 0xfeaf0000
1646#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647#else
1648#error unknown architecture
1649#endif
1650
1651 if (tcp->flags & TCB_BPTSET) {
1652 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1653 return -1;
1654 }
1655#if defined (I386)
1656 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1657 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001658#elif defined (X86_64)
1659 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1660 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661#elif defined (M68K)
1662 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1663 return -1;
1664#elif defined (ALPHA)
1665 return -1;
1666#elif defined (ARM)
1667 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001668#elif defined (MIPS)
1669 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001671 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001673#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001674 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1675 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001676#elif defined(HPPA)
1677 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1678 return -1;
1679 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001680#elif defined(SH)
1681 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1682 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683#else
1684#error unknown architecture
1685#endif
1686 if (debug)
1687 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1688 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1689 if (errno) {
1690 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1691 return -1;
1692 }
1693 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1694 if (errno) {
1695 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1696 return -1;
1697 }
1698 tcp->flags |= TCB_BPTSET;
1699
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001700#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001701#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702#endif /* LINUX */
1703
1704#ifdef SUNOS4
1705#ifdef SPARC /* This code is slightly sparc specific */
1706
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001707 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001708#define BPT 0x91d02001 /* ta 1 */
1709#define LOOP 0x10800000 /* ba 0 */
1710#define LOOPA 0x30800000 /* ba,a 0 */
1711#define NOP 0x01000000
1712#if LOOPA
1713 static int loopdeloop[1] = {LOOPA};
1714#else
1715 static int loopdeloop[2] = {LOOP, NOP};
1716#endif
1717
1718 if (tcp->flags & TCB_BPTSET) {
1719 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1720 return -1;
1721 }
1722 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1723 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1724 return -1;
1725 }
1726 tcp->baddr = regs.r_o7 + 8;
1727 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1728 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1729 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1730 return -1;
1731 }
1732
1733 /*
1734 * XXX - BRUTAL MODE ON
1735 * We cannot set a real BPT in the child, since it will not be
1736 * traced at the moment it will reach the trap and would probably
1737 * die with a core dump.
1738 * Thus, we are force our way in by taking out two instructions
1739 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1740 * generated by out PTRACE_ATTACH.
1741 * Of cause, if we evaporate ourselves in the middle of all this...
1742 */
1743 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1744 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1745 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1746 return -1;
1747 }
1748 tcp->flags |= TCB_BPTSET;
1749
1750#endif /* SPARC */
1751#endif /* SUNOS4 */
1752
1753 return 0;
1754}
1755
1756int
1757clearbpt(tcp)
1758struct tcb *tcp;
1759{
1760
1761#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001762#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001764#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001766#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001767 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001768#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001769 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001770#elif defined(HPPA)
1771 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001772#elif defined(SH)
1773 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001774#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001776#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777 /* Again, we borrow the SunOS breakpoint code. */
1778 if (!(tcp->flags & TCB_BPTSET)) {
1779 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1780 return -1;
1781 }
1782 errno = 0;
1783 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1784 if(errno) {
1785 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1786 return -1;
1787 }
1788 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001789#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001790 if (ia32) {
1791 unsigned long addr;
1792
1793 if (debug)
1794 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1795 if (!(tcp->flags & TCB_BPTSET)) {
1796 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1797 return -1;
1798 }
1799 errno = 0;
1800 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1801 if (errno) {
1802 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1803 return -1;
1804 }
1805 tcp->flags &= ~TCB_BPTSET;
1806
1807 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1808 return -1;
1809 if (addr != tcp->baddr) {
1810 /* The breakpoint has not been reached yet. */
1811 if (debug)
1812 fprintf(stderr,
1813 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1814 addr, tcp->baddr);
1815 return 0;
1816 }
1817 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001818 unsigned long addr, ipsr;
1819 pid_t pid;
1820
1821 pid = tcp->pid;
1822
1823 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1824 return -1;
1825 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1826 return -1;
1827
1828 /* restore original bundle: */
1829 errno = 0;
1830 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1831 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1832 if (errno) {
1833 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1834 return -1;
1835 }
1836
1837 /* restore original "ri" in ipsr: */
1838 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1839 errno = 0;
1840 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1841 if (errno) {
1842 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1843 return -1;
1844 }
1845
1846 tcp->flags &= ~TCB_BPTSET;
1847
1848 if (addr != (tcp->baddr & ~0x3)) {
1849 /* the breakpoint has not been reached yet. */
1850 if (debug)
1851 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1852 addr, tcp->baddr);
1853 return 0;
1854 }
1855 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001856#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001857
1858 if (debug)
1859 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1860 if (!(tcp->flags & TCB_BPTSET)) {
1861 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1862 return -1;
1863 }
1864 errno = 0;
1865 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1866 if (errno) {
1867 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1868 return -1;
1869 }
1870 tcp->flags &= ~TCB_BPTSET;
1871
1872#ifdef I386
1873 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1874 return -1;
1875 if (eip != tcp->baddr) {
1876 /* The breakpoint has not been reached yet. */
1877 if (debug)
1878 fprintf(stderr,
1879 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1880 eip, tcp->baddr);
1881 return 0;
1882 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001883#elif defined(X86_64)
1884 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1885 return -1;
1886 if (eip != tcp->baddr) {
1887 /* The breakpoint has not been reached yet. */
1888 if (debug)
1889 fprintf(stderr,
1890 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1891 eip, tcp->baddr);
1892 return 0;
1893 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001894#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001895 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001896 return -1;
1897 if (pc != tcp->baddr) {
1898 /* The breakpoint has not been reached yet. */
1899 if (debug)
1900 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1901 pc, tcp->baddr);
1902 return 0;
1903 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001904#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001905 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1906 return -1;
1907 if (pc != tcp->baddr) {
1908 /* The breakpoint has not been reached yet. */
1909 if (debug)
1910 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1911 pc, tcp->baddr);
1912 return 0;
1913 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001914#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001915 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1916 return -1;
1917 if (pc != tcp->baddr) {
1918 /* The breakpoint has not been reached yet. */
1919 if (debug)
1920 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1921 pc, tcp->baddr);
1922 return 0;
1923 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001924#elif defined(HPPA)
1925 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1926 return -1;
1927 iaoq &= ~0x03;
1928 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1929 /* The breakpoint has not been reached yet. */
1930 if (debug)
1931 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1932 iaoq, tcp->baddr);
1933 return 0;
1934 }
1935 iaoq = tcp->baddr | 3;
1936 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1937 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1938 * has no significant effect.
1939 */
1940 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1941 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001942#elif defined(SH)
1943 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1944 return -1;
1945 if (pc != tcp->baddr) {
1946 /* The breakpoint has not been reached yet. */
1947 if (debug)
1948 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1949 pc, tcp->baddr);
1950 return 0;
1951 }
1952
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001953#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001954#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001955#endif /* LINUX */
1956
1957#ifdef SUNOS4
1958#ifdef SPARC
1959
1960#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001961 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001962#endif
1963
1964 if (!(tcp->flags & TCB_BPTSET)) {
1965 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1966 return -1;
1967 }
1968 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1969 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1970 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1971 return -1;
1972 }
1973 tcp->flags &= ~TCB_BPTSET;
1974
1975#if !LOOPA
1976 /*
1977 * Since we don't have a single instruction breakpoint, we may have
1978 * to adjust the program counter after removing the our `breakpoint'.
1979 */
1980 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1981 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1982 return -1;
1983 }
1984 if ((regs.r_pc < tcp->baddr) ||
1985 (regs.r_pc > tcp->baddr + 4)) {
1986 /* The breakpoint has not been reached yet */
1987 if (debug)
1988 fprintf(stderr,
1989 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1990 regs.r_pc, tcp->parent->baddr);
1991 return 0;
1992 }
1993 if (regs.r_pc != tcp->baddr)
1994 if (debug)
1995 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1996 regs.r_pc, tcp->baddr);
1997
1998 regs.r_pc = tcp->baddr;
1999 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2000 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2001 return -1;
2002 }
2003#endif /* LOOPA */
2004#endif /* SPARC */
2005#endif /* SUNOS4 */
2006
2007 return 0;
2008}
2009
Roland McGrathd81f1d92003-01-09 06:53:34 +00002010#endif
2011
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002012#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002013
2014#ifdef SUNOS4
2015
2016static int
2017getex(pid, hdr)
2018int pid;
2019struct exec *hdr;
2020{
2021 int n;
2022
2023 for (n = 0; n < sizeof *hdr; n += 4) {
2024 long res;
2025 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2026 return -1;
2027 memcpy(((char *) hdr) + n, &res, 4);
2028 }
2029 if (debug) {
2030 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2031 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2032 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2033 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2034 }
2035 return 0;
2036}
2037
2038int
2039fixvfork(tcp)
2040struct tcb *tcp;
2041{
2042 int pid = tcp->pid;
2043 /*
2044 * Change `vfork' in a freshly exec'ed dynamically linked
2045 * executable's (internal) symbol table to plain old `fork'
2046 */
2047
2048 struct exec hdr;
2049 struct link_dynamic dyn;
2050 struct link_dynamic_2 ld;
2051 char *strtab, *cp;
2052
2053 if (getex(pid, &hdr) < 0)
2054 return -1;
2055 if (!hdr.a_dynamic)
2056 return -1;
2057
2058 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2059 fprintf(stderr, "Cannot read DYNAMIC\n");
2060 return -1;
2061 }
2062 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2063 fprintf(stderr, "Cannot read link_dynamic_2\n");
2064 return -1;
2065 }
2066 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002067 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002068 return -1;
2069 }
2070 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2071 (int)ld.ld_symb_size, strtab) < 0)
2072 goto err;
2073
2074#if 0
2075 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2076 fprintf(stderr, "[symbol: %s]\n", cp);
2077 cp += strlen(cp)+1;
2078 }
2079 return 0;
2080#endif
2081 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2082 if (strcmp(cp, "_vfork") == 0) {
2083 if (debug)
2084 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2085 strcpy(cp, "_fork");
2086 break;
2087 }
2088 cp += strlen(cp)+1;
2089 }
2090 if (cp < strtab + ld.ld_symb_size)
2091 /*
2092 * Write entire symbol table back to avoid
2093 * memory alignment bugs in ptrace
2094 */
2095 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2096 (int)ld.ld_symb_size, strtab) < 0)
2097 goto err;
2098
2099 free(strtab);
2100 return 0;
2101
2102err:
2103 free(strtab);
2104 return -1;
2105}
2106
2107#endif /* SUNOS4 */