blob: d65f42ced7ea9003f9c1cf6d5a6dc228f9b6ac07 [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
353printuid(text, uid)
354const char *text;
355unsigned long uid;
356{
357 tprintf("%s", text);
358 tprintf((uid == -1) ? "%ld" : "%lu", uid);
359}
360
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000361static char path[MAXPATHLEN + 1];
362
Roland McGratha4d48532005-06-08 20:45:28 +0000363static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364string_quote(str)
Roland McGratha4d48532005-06-08 20:45:28 +0000365const char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000366{
367 char buf[2 * MAXPATHLEN + 1];
368 char *s;
369
370 if (!strpbrk(str, "\"\'\\")) {
371 tprintf("\"%s\"", str);
372 return;
373 }
374 for (s = buf; *str; str++) {
375 switch (*str) {
376 case '\"': case '\'': case '\\':
377 *s++ = '\\'; *s++ = *str; break;
378 default:
379 *s++ = *str; break;
380 }
381 }
382 *s = '\0';
383 tprintf("\"%s\"", buf);
384}
385
386void
387printpath(tcp, addr)
388struct tcb *tcp;
389long addr;
390{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000391 if (addr == 0)
392 tprintf("NULL");
393 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000394 tprintf("%#lx", addr);
395 else
396 string_quote(path);
397 return;
398}
399
400void
401printpathn(tcp, addr, n)
402struct tcb *tcp;
403long addr;
404int n;
405{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000406 if (addr == 0)
407 tprintf("NULL");
408 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000409 tprintf("%#lx", addr);
410 else {
411 path[n] = '\0';
412 string_quote(path);
413 }
414}
415
416void
417printstr(tcp, addr, len)
418struct tcb *tcp;
419long addr;
420int len;
421{
422 static unsigned char *str = NULL;
423 static char *outstr;
424 int i, n, c, usehex;
425 char *s, *outend;
426
427 if (!addr) {
428 tprintf("NULL");
429 return;
430 }
431 if (!str) {
432 if ((str = malloc(max_strlen)) == NULL
433 || (outstr = malloc(2*max_strlen)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000434 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000435 tprintf("%#lx", addr);
436 return;
437 }
438 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000439 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000440 if (len < 0) {
441 n = max_strlen;
442 if (umovestr(tcp, addr, n, (char *) str) < 0) {
443 tprintf("%#lx", addr);
444 return;
445 }
446 }
447 else {
448 n = MIN(len, max_strlen);
449 if (umoven(tcp, addr, n, (char *) str) < 0) {
450 tprintf("%#lx", addr);
451 return;
452 }
453 }
454
455 usehex = 0;
456 if (xflag > 1)
457 usehex = 1;
458 else if (xflag) {
459 for (i = 0; i < n; i++) {
460 c = str[i];
461 if (len < 0 && c == '\0')
462 break;
463 if (!isprint(c) && !isspace(c)) {
464 usehex = 1;
465 break;
466 }
467 }
468 }
469
470 s = outstr;
471 *s++ = '\"';
472
473 if (usehex) {
474 for (i = 0; i < n; i++) {
475 c = str[i];
476 if (len < 0 && c == '\0')
477 break;
478 sprintf(s, "\\x%02x", c);
479 s += 4;
480 if (s > outend)
481 break;
482 }
483 }
484 else {
485 for (i = 0; i < n; i++) {
486 c = str[i];
487 if (len < 0 && c == '\0')
488 break;
489 switch (c) {
490 case '\"': case '\'': case '\\':
491 *s++ = '\\'; *s++ = c; break;
492 case '\f':
493 *s++ = '\\'; *s++ = 'f'; break;
494 case '\n':
495 *s++ = '\\'; *s++ = 'n'; break;
496 case '\r':
497 *s++ = '\\'; *s++ = 'r'; break;
498 case '\t':
499 *s++ = '\\'; *s++ = 't'; break;
500 case '\v':
501 *s++ = '\\'; *s++ = 'v'; break;
502 default:
503 if (isprint(c))
504 *s++ = c;
505 else if (i < n - 1 && isdigit(str[i + 1])) {
506 sprintf(s, "\\%03o", c);
507 s += 4;
508 }
509 else {
510 sprintf(s, "\\%o", c);
511 s += strlen(s);
512 }
513 break;
514 }
515 if (s > outend)
516 break;
517 }
518 }
519
520 *s++ = '\"';
521 if (i < len || (len < 0 && (i == n || s > outend))) {
522 *s++ = '.'; *s++ = '.'; *s++ = '.';
523 }
524 *s = '\0';
525 tprintf("%s", outstr);
526}
527
John Hughes1d08dcf2001-07-10 13:48:44 +0000528#if HAVE_SYS_UIO_H
529void
530dumpiov(tcp, len, addr)
531struct tcb * tcp;
532int len;
533long addr;
534{
535 struct iovec *iov;
536 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000537 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000538
Roland McGrathaa524c82005-06-01 19:22:06 +0000539 size = sizeof(*iov) * (unsigned long) len;
540 if (size / sizeof(*iov) != len
541 || (iov = (struct iovec *) malloc(size)) == NULL) {
542 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000543 return;
544 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000545 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000546 for (i = 0; i < len; i++) {
547 /* include the buffer number to make it easy to
548 * match up the trace with the source */
549 tprintf(" * %lu bytes in buffer %d\n",
550 (unsigned long)iov[i].iov_len, i);
551 dumpstr(tcp, (long) iov[i].iov_base,
552 iov[i].iov_len);
553 }
554 }
555 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000556
John Hughes1d08dcf2001-07-10 13:48:44 +0000557}
558#endif
559
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560void
561dumpstr(tcp, addr, len)
562struct tcb *tcp;
563long addr;
564int len;
565{
566 static int strsize = -1;
567 static unsigned char *str;
568 static char outstr[80];
569 char *s;
570 int i, j;
571
572 if (strsize < len) {
573 if (str)
574 free(str);
575 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000576 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000577 return;
578 }
579 strsize = len;
580 }
581
582 if (umoven(tcp, addr, len, (char *) str) < 0)
583 return;
584
585 for (i = 0; i < len; i += 16) {
586 s = outstr;
587 sprintf(s, " | %05x ", i);
588 s += 9;
589 for (j = 0; j < 16; j++) {
590 if (j == 8)
591 *s++ = ' ';
592 if (i + j < len) {
593 sprintf(s, " %02x", str[i + j]);
594 s += 3;
595 }
596 else {
597 *s++ = ' '; *s++ = ' '; *s++ = ' ';
598 }
599 }
600 *s++ = ' '; *s++ = ' ';
601 for (j = 0; j < 16; j++) {
602 if (j == 8)
603 *s++ = ' ';
604 if (i + j < len) {
605 if (isprint(str[i + j]))
606 *s++ = str[i + j];
607 else
608 *s++ = '.';
609 }
610 else
611 *s++ = ' ';
612 }
613 tprintf("%s |\n", outstr);
614 }
615}
616
617#define PAGMASK (~(PAGSIZ - 1))
618/*
619 * move `len' bytes of data from process `pid'
620 * at address `addr' to our space at `laddr'
621 */
622int
623umoven(tcp, addr, len, laddr)
624struct tcb *tcp;
625long addr;
626int len;
627char *laddr;
628{
629
630#ifdef LINUX
631 int pid = tcp->pid;
632 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000633 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000634 union {
635 long val;
636 char x[sizeof(long)];
637 } u;
638
639 if (addr & (sizeof(long) - 1)) {
640 /* addr not a multiple of sizeof(long) */
641 n = addr - (addr & -sizeof(long)); /* residue */
642 addr &= -sizeof(long); /* residue */
643 errno = 0;
644 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
645 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000646 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000647 /* Ran into 'end of memory' - stupid "printpath" */
648 return 0;
649 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000650 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000651 perror("ptrace: umoven");
652 return -1;
653 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000654 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
656 addr += sizeof(long), laddr += m, len -= m;
657 }
658 while (len) {
659 errno = 0;
660 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
661 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000662 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000663 /* Ran into 'end of memory' - stupid "printpath" */
664 return 0;
665 }
Roland McGrath4db26242003-01-30 20:15:19 +0000666 if (addr != 0)
667 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000668 return -1;
669 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000670 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000671 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
672 addr += sizeof(long), laddr += m, len -= m;
673 }
674#endif /* LINUX */
675
676#ifdef SUNOS4
677 int pid = tcp->pid;
678#if 0
679 int n, m;
680 union {
681 long val;
682 char x[sizeof(long)];
683 } u;
684
685 if (addr & (sizeof(long) - 1)) {
686 /* addr not a multiple of sizeof(long) */
687 n = addr - (addr & -sizeof(long)); /* residue */
688 addr &= -sizeof(long); /* residue */
689 errno = 0;
690 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
691 if (errno) {
692 perror("umoven");
693 return -1;
694 }
695 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
696 addr += sizeof(long), laddr += m, len -= m;
697 }
698 while (len) {
699 errno = 0;
700 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
701 if (errno) {
702 perror("umoven");
703 return -1;
704 }
705 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
706 addr += sizeof(long), laddr += m, len -= m;
707 }
708#else /* !oldway */
709 int n;
710
711 while (len) {
712 n = MIN(len, PAGSIZ);
713 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
714 if (ptrace(PTRACE_READDATA, pid,
715 (char *) addr, len, laddr) < 0) {
716 perror("umoven: ptrace(PTRACE_READDATA, ...)");
717 abort();
718 return -1;
719 }
720 len -= n;
721 addr += n;
722 laddr += n;
723 }
724#endif /* !oldway */
725#endif /* SUNOS4 */
726
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000727#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000728#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000729 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000730#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000731 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000733 lseek(fd, addr, SEEK_SET);
734 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000736#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000737
738 return 0;
739}
740
741/*
742 * like `umove' but make the additional effort of looking
743 * for a terminating zero byte.
744 */
745int
746umovestr(tcp, addr, len, laddr)
747struct tcb *tcp;
748long addr;
749int len;
750char *laddr;
751{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000752#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000753#ifdef HAVE_MP_PROCFS
754 int fd = tcp->pfd_as;
755#else
756 int fd = tcp->pfd;
757#endif
758 /* Some systems (e.g. FreeBSD) can be upset if we read off the
759 end of valid memory, avoid this by trying to read up
760 to page boundaries. But we don't know what a page is (and
761 getpagesize(2) (if it exists) doesn't necessarily return
762 hardware page size). Assume all pages >= 1024 (a-historical
763 I know) */
764
765 int page = 1024; /* How to find this? */
766 int move = page - (addr & (page - 1));
767 int left = len;
768
769 lseek(fd, addr, SEEK_SET);
770
771 while (left) {
772 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000773 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000774 return left != len ? 0 : -1;
775 if (memchr (laddr, 0, move)) break;
776 left -= move;
777 laddr += move;
778 addr += move;
779 move = page;
780 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000781#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000782 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783 int pid = tcp->pid;
784 int i, n, m;
785 union {
786 long val;
787 char x[sizeof(long)];
788 } u;
789
790 if (addr & (sizeof(long) - 1)) {
791 /* addr not a multiple of sizeof(long) */
792 n = addr - (addr & -sizeof(long)); /* residue */
793 addr &= -sizeof(long); /* residue */
794 errno = 0;
795 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
796 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000797 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000798 /* Ran into 'end of memory' - stupid "printpath" */
799 return 0;
800 }
801 perror("umovestr");
802 return -1;
803 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000804 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
806 while (n & (sizeof(long) - 1))
807 if (u.x[n++] == '\0')
808 return 0;
809 addr += sizeof(long), laddr += m, len -= m;
810 }
811 while (len) {
812 errno = 0;
813 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
814 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000815 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816 /* Ran into 'end of memory' - stupid "printpath" */
817 return 0;
818 }
819 perror("umovestr");
820 return -1;
821 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000822 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000823 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
824 for (i = 0; i < sizeof(long); i++)
825 if (u.x[i] == '\0')
826 return 0;
827
828 addr += sizeof(long), laddr += m, len -= m;
829 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000830#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000831 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000832}
833
834#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000835#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000836#define PTRACE_WRITETEXT 101
837#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000838#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000839#endif /* LINUX */
840
841#ifdef SUNOS4
842
843static int
844uload(cmd, pid, addr, len, laddr)
845int cmd;
846int pid;
847long addr;
848int len;
849char *laddr;
850{
851#if 0
852 int n;
853
854 while (len) {
855 n = MIN(len, PAGSIZ);
856 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
857 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
858 perror("uload: ptrace(PTRACE_WRITE, ...)");
859 return -1;
860 }
861 len -= n;
862 addr += n;
863 laddr += n;
864 }
865#else
866 int peek, poke;
867 int n, m;
868 union {
869 long val;
870 char x[sizeof(long)];
871 } u;
872
873 if (cmd == PTRACE_WRITETEXT) {
874 peek = PTRACE_PEEKTEXT;
875 poke = PTRACE_POKETEXT;
876 }
877 else {
878 peek = PTRACE_PEEKDATA;
879 poke = PTRACE_POKEDATA;
880 }
881 if (addr & (sizeof(long) - 1)) {
882 /* addr not a multiple of sizeof(long) */
883 n = addr - (addr & -sizeof(long)); /* residue */
884 addr &= -sizeof(long);
885 errno = 0;
886 u.val = ptrace(peek, pid, (char *) addr, 0);
887 if (errno) {
888 perror("uload: POKE");
889 return -1;
890 }
891 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
892 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
893 perror("uload: POKE");
894 return -1;
895 }
896 addr += sizeof(long), laddr += m, len -= m;
897 }
898 while (len) {
899 if (len < sizeof(long))
900 u.val = ptrace(peek, pid, (char *) addr, 0);
901 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
902 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
903 perror("uload: POKE");
904 return -1;
905 }
906 addr += sizeof(long), laddr += m, len -= m;
907 }
908#endif
909 return 0;
910}
911
912int
913tload(pid, addr, len, laddr)
914int pid;
915int addr, len;
916char *laddr;
917{
918 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
919}
920
921int
922dload(pid, addr, len, laddr)
923int pid;
924int addr;
925int len;
926char *laddr;
927{
928 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
929}
930
931#endif /* SUNOS4 */
932
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000933#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000934
935int
936upeek(pid, off, res)
937int pid;
938long off;
939long *res;
940{
941 long val;
942
943#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
944 {
945 static int is_sun4m = -1;
946 struct utsname name;
947
948 /* Round up the usual suspects. */
949 if (is_sun4m == -1) {
950 if (uname(&name) < 0) {
951 perror("upeek: uname?");
952 exit(1);
953 }
954 is_sun4m = strcmp(name.machine, "sun4m") == 0;
955 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000956 extern const struct xlat struct_user_offsets[];
957 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958
959 for (x = struct_user_offsets; x->str; x++)
960 x->val += 1024;
961 }
962 }
963 if (is_sun4m)
964 off += 1024;
965 }
966#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
967 errno = 0;
968 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
969 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000970 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000971 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000972 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 return -1;
974 }
975 *res = val;
976 return 0;
977}
978
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000979#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000980
Roland McGratha4d48532005-06-08 20:45:28 +0000981#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982long
983getpc(tcp)
984struct tcb *tcp;
985{
986
987#ifdef LINUX
988 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000989#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
991 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000992#elif defined(X86_64)
993 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
994 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000995#elif defined(IA64)
996 if (upeek(tcp->pid, PT_B0, &pc) < 0)
997 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000998#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000999 if (upeek(tcp->pid, 4*15, &pc) < 0)
1000 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001001#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001002 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001004#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1006 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001007#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1009 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001010#elif defined(MIPS)
1011 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1012 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001013#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001014 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1016 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001017 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001018#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001019 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001020 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001021#elif defined(HPPA)
1022 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1023 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001024#elif defined(SH)
1025 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1026 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001027#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001028 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1029 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001030#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 return pc;
1032#endif /* LINUX */
1033
1034#ifdef SUNOS4
1035 /*
1036 * Return current program counter for `pid'
1037 * Assumes PC is never 0xffffffff
1038 */
1039 struct regs regs;
1040
1041 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1042 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1043 return -1;
1044 }
1045 return regs.r_pc;
1046#endif /* SUNOS4 */
1047
1048#ifdef SVR4
1049 /* XXX */
1050 return 0;
1051#endif /* SVR4 */
1052
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001053#ifdef FREEBSD
1054 struct reg regs;
1055 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1056 return regs.r_eip;
1057#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058}
Roland McGratha4d48532005-06-08 20:45:28 +00001059#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060
1061void
1062printcall(tcp)
1063struct tcb *tcp;
1064{
Roland McGrath7a918832005-02-02 20:55:23 +00001065#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1066 sizeof(long) == 8 ? "[????????????????] " : \
1067 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001068
1069#ifdef LINUX
1070#ifdef I386
1071 long eip;
1072
1073 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001074 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 return;
1076 }
1077 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001078
1079#elif defined(S390) || defined(S390X)
1080 long psw;
1081 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001082 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001083 return;
1084 }
1085#ifdef S390
1086 tprintf("[%08lx] ", psw);
1087#elif S390X
1088 tprintf("[%16lx] ", psw);
1089#endif
1090
Michal Ludvig0e035502002-09-23 15:41:01 +00001091#elif defined(X86_64)
1092 long rip;
1093
1094 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001095 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001096 return;
1097 }
1098 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001099#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001100 long ip;
1101
1102 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001103 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001104 return;
1105 }
1106 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001107#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001108 long pc;
1109
Roland McGratheb285352003-01-14 09:59:00 +00001110 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001111 tprintf ("[????????] ");
1112 return;
1113 }
1114 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001115#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001116 long pc;
1117
1118 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1119 tprintf ("[????????] ");
1120 return;
1121 }
1122 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001123#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 long pc;
1125
1126 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001127 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 return;
1129 }
1130 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001131#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001132 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001134 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001135 return;
1136 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001137 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001138#elif defined(HPPA)
1139 long pc;
1140
1141 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1142 tprintf ("[????????] ");
1143 return;
1144 }
1145 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001146#elif defined(MIPS)
1147 long pc;
1148
1149 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1150 tprintf ("[????????] ");
1151 return;
1152 }
1153 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001154#elif defined(SH)
1155 long pc;
1156
1157 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1158 tprintf ("[????????] ");
1159 return;
1160 }
1161 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001162#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001163 long pc;
1164
1165 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001166 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001167 return;
1168 }
1169 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001170#elif defined(ARM)
1171 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001172
Roland McGrathef388682003-06-03 23:28:59 +00001173 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001174 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001175 return;
1176 }
1177 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001178#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001179#endif /* LINUX */
1180
1181#ifdef SUNOS4
1182 struct regs regs;
1183
1184 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1185 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001186 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 return;
1188 }
1189 tprintf("[%08x] ", regs.r_o7);
1190#endif /* SUNOS4 */
1191
1192#ifdef SVR4
1193 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001194 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001195#endif
1196
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001197#ifdef FREEBSD
1198 struct reg regs;
1199 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1200 tprintf("[%08x] ", regs.r_eip);
1201#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202}
1203
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001204#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205
Roland McGrathd81f1d92003-01-09 06:53:34 +00001206#if defined LINUX
1207
1208#include <sys/syscall.h>
1209#ifndef CLONE_PTRACE
1210# define CLONE_PTRACE 0x00002000
1211#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001212#ifndef CLONE_STOPPED
1213# define CLONE_STOPPED 0x02000000
1214#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001215
1216#ifdef IA64
1217
Roland McGrath08267b82004-02-20 22:56:43 +00001218/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1219 subsystem has them for x86... */
1220#define SYS_fork 2
1221#define SYS_vfork 190
1222
Roland McGrathd81f1d92003-01-09 06:53:34 +00001223typedef unsigned long *arg_setup_state;
1224
1225static int
1226arg_setup(struct tcb *tcp, arg_setup_state *state)
1227{
1228 unsigned long *bsp, cfm, sof, sol;
1229
Roland McGrath08267b82004-02-20 22:56:43 +00001230 if (ia32)
1231 return 0;
1232
Roland McGrathd81f1d92003-01-09 06:53:34 +00001233 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1234 return -1;
1235 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1236 return -1;
1237
1238 sof = (cfm >> 0) & 0x7f;
1239 sol = (cfm >> 7) & 0x7f;
1240 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1241
1242 *state = bsp;
1243 return 0;
1244}
1245
1246# define arg_finish_change(tcp, state) 0
1247
1248#ifdef SYS_fork
1249static int
1250get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1251{
Roland McGrath08267b82004-02-20 22:56:43 +00001252 int ret;
1253
1254 if (ia32)
1255 ret = upeek (tcp->pid, PT_R11, valp);
1256 else
1257 ret = umoven (tcp,
1258 (unsigned long) ia64_rse_skip_regs(*state, 0),
1259 sizeof(long), (void *) valp);
1260 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001261}
1262
1263static int
1264get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1265{
Roland McGrath08267b82004-02-20 22:56:43 +00001266 int ret;
1267
1268 if (ia32)
1269 ret = upeek (tcp->pid, PT_R9, valp);
1270 else
1271 ret = umoven (tcp,
1272 (unsigned long) ia64_rse_skip_regs(*state, 1),
1273 sizeof(long), (void *) valp);
1274 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275}
1276#endif
1277
1278static int
1279set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1280{
Roland McGrath08267b82004-02-20 22:56:43 +00001281 int req = PTRACE_POKEDATA;
1282 void *ap;
1283
1284 if (ia32) {
1285 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1286 req = PTRACE_POKEUSER;
1287 } else
1288 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001289 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001290 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001291 return errno ? -1 : 0;
1292}
1293
1294static int
1295set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1296{
Roland McGrath08267b82004-02-20 22:56:43 +00001297 int req = PTRACE_POKEDATA;
1298 void *ap;
1299
1300 if (ia32) {
1301 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1302 req = PTRACE_POKEUSER;
1303 } else
1304 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001305 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001306 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001307 return errno ? -1 : 0;
1308}
1309
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001310#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001311
1312typedef struct regs arg_setup_state;
1313
1314# define arg_setup(tcp, state) \
1315 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1316# define arg_finish_change(tcp, state) \
1317 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1318
1319# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1320# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1321# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1322# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001323# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001324
1325#else
1326
1327# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001328/* Note: this is only true for the `clone' system call, which handles
1329 arguments specially. We could as well say that its first two arguments
1330 are swapped relative to other architectures, but that would just be
1331 another #ifdef in the calls. */
1332# define arg0_offset PT_GPR3
1333# define arg1_offset PT_ORIGGPR2
1334# define restore_arg0(tcp, state, val) ((void) (state), 0)
1335# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001336# define arg0_index 1
1337# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338# elif defined (ALPHA) || defined (MIPS)
1339# define arg0_offset REG_A0
1340# define arg1_offset (REG_A0+1)
1341# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001342# define arg0_offset (sizeof(unsigned long)*PT_R3)
1343# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001344# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001345# elif defined (HPPA)
1346# define arg0_offset PT_GR26
1347# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001348# elif defined (X86_64)
1349# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1350# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001351# elif defined (SH)
1352# define arg0_offset (4*(REG_REG0+4))
1353# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001354# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001355 /* ABI defines arg0 & 1 in r2 & r3 */
1356# define arg0_offset (REG_OFFSET+16)
1357# define arg1_offset (REG_OFFSET+24)
1358# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001359# else
1360# define arg0_offset 0
1361# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001362# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001363# define restore_arg0(tcp, state, val) 0
1364# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001365# endif
1366
1367typedef int arg_setup_state;
1368
1369# define arg_setup(tcp, state) (0)
1370# define arg_finish_change(tcp, state) 0
1371# define get_arg0(tcp, cookie, valp) \
1372 (upeek ((tcp)->pid, arg0_offset, (valp)))
1373# define get_arg1(tcp, cookie, valp) \
1374 (upeek ((tcp)->pid, arg1_offset, (valp)))
1375
1376static int
1377set_arg0 (struct tcb *tcp, void *cookie, long val)
1378{
Roland McGrathca85b972005-06-07 23:22:08 +00001379 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001380}
1381
1382static int
1383set_arg1 (struct tcb *tcp, void *cookie, long val)
1384{
1385 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1386}
1387
1388#endif
1389
Roland McGrathe1df47f2003-01-14 09:46:15 +00001390#ifndef restore_arg0
1391# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1392#endif
1393#ifndef restore_arg1
1394# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1395#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001396
Roland McGrath90d0afd2004-03-01 21:05:16 +00001397#ifndef arg0_index
1398# define arg0_index 0
1399# define arg1_index 1
1400#endif
1401
Roland McGrathd81f1d92003-01-09 06:53:34 +00001402int
1403setbpt(tcp)
1404struct tcb *tcp;
1405{
1406 extern int change_syscall(struct tcb *, int);
1407 arg_setup_state state;
1408
1409 if (tcp->flags & TCB_BPTSET) {
1410 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1411 return -1;
1412 }
1413
Roland McGrath76989d72005-06-07 23:21:31 +00001414 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001415#ifdef SYS_vfork
1416 case SYS_vfork:
1417#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001418#ifdef SYS_fork
1419 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001420#endif
1421#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001422 if (arg_setup (tcp, &state) < 0
1423 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1424 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1425 || change_syscall(tcp, SYS_clone) < 0
1426 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1427 || set_arg1 (tcp, &state, 0) < 0
1428 || arg_finish_change (tcp, &state) < 0)
1429 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001430 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1431 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001432 tcp->flags |= TCB_BPTSET;
1433 return 0;
1434#endif
1435
1436 case SYS_clone:
1437#ifdef SYS_clone2
1438 case SYS_clone2:
1439#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001440 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001441 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001442 || set_arg0 (tcp, &state,
1443 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001444 || arg_finish_change (tcp, &state) < 0))
1445 return -1;
1446 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001447 tcp->inst[0] = tcp->u_arg[arg0_index];
1448 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001449 return 0;
1450
1451 default:
1452 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1453 tcp->scno, tcp->pid);
1454 break;
1455 }
1456
1457 return -1;
1458}
1459
1460int
1461clearbpt(tcp)
1462struct tcb *tcp;
1463{
1464 arg_setup_state state;
1465 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001466 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1467 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001468 || arg_finish_change (tcp, &state))
1469 return -1;
1470 tcp->flags &= ~TCB_BPTSET;
1471 return 0;
1472}
1473
1474#else
1475
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476int
1477setbpt(tcp)
1478struct tcb *tcp;
1479{
1480
1481#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001482#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 /* We simply use the SunOS breakpoint code. */
1484
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001485 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001486 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487#define LOOPA 0x30800000 /* ba,a 0 */
1488
1489 if (tcp->flags & TCB_BPTSET) {
1490 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1491 return -1;
1492 }
1493 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1494 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1495 return -1;
1496 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001497 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498 errno = 0;
1499 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1500 if(errno) {
1501 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1502 return -1;
1503 }
1504
1505 /*
1506 * XXX - BRUTAL MODE ON
1507 * We cannot set a real BPT in the child, since it will not be
1508 * traced at the moment it will reach the trap and would probably
1509 * die with a core dump.
1510 * Thus, we are force our way in by taking out two instructions
1511 * and insert an eternal loop instead, in expectance of the SIGSTOP
1512 * generated by out PTRACE_ATTACH.
1513 * Of cause, if we evaporate ourselves in the middle of all this...
1514 */
1515 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001516 inst = LOOPA;
1517#if defined (SPARC64)
1518 inst <<= 32;
1519 inst |= (tcp->inst[0] & 0xffffffffUL);
1520#endif
1521 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001522 if(errno) {
1523 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1524 return -1;
1525 }
1526 tcp->flags |= TCB_BPTSET;
1527
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001528#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001529#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001530 if (ia32) {
1531# define LOOP 0x0000feeb
1532 if (tcp->flags & TCB_BPTSET) {
1533 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1534 tcp->pid);
1535 return -1;
1536 }
1537 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1538 return -1;
1539 if (debug)
1540 fprintf(stderr, "[%d] setting bpt at %lx\n",
1541 tcp->pid, tcp->baddr);
1542 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1543 (char *) tcp->baddr, 0);
1544 if (errno) {
1545 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1546 return -1;
1547 }
1548 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1549 if (errno) {
1550 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1551 return -1;
1552 }
1553 tcp->flags |= TCB_BPTSET;
1554 } else {
1555 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001556 * Our strategy here is to replace the bundle that
1557 * contained the clone() syscall with a bundle of the
1558 * form:
1559 *
1560 * { 1: br 1b; br 1b; br 1b }
1561 *
1562 * This ensures that the newly forked child will loop
1563 * endlessly until we've got a chance to attach to it.
1564 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001565# define LOOP0 0x0000100000000017
1566# define LOOP1 0x4000000000200000
1567 unsigned long addr, ipsr;
1568 pid_t pid;
1569
1570 pid = tcp->pid;
1571 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1572 return -1;
1573 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1574 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001575 /* store "ri" in low two bits */
1576 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001577
1578 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001579 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1580 0);
1581 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1582 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001583 if (errno) {
1584 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1585 return -1;
1586 }
1587
1588 errno = 0;
1589 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1590 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1591 if (errno) {
1592 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1593 return -1;
1594 }
1595 tcp->flags |= TCB_BPTSET;
1596 }
1597#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598
Michal Ludvig0e035502002-09-23 15:41:01 +00001599#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001600#define LOOP 0x0000feeb
1601#elif defined (M68K)
1602#define LOOP 0x60fe0000
1603#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001604#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001606#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001607#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001608#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001609#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001610#define LOOP 0x1000ffff
1611#elif defined(S390)
1612#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001613#elif defined(S390X)
1614#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001615#elif defined(HPPA)
1616#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001617#elif defined(SH)
1618#ifdef __LITTLE_ENDIAN__
1619#define LOOP 0x0000affe
1620#else
1621#define LOOP 0xfeaf0000
1622#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623#else
1624#error unknown architecture
1625#endif
1626
1627 if (tcp->flags & TCB_BPTSET) {
1628 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1629 return -1;
1630 }
1631#if defined (I386)
1632 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1633 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001634#elif defined (X86_64)
1635 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1636 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001637#elif defined (M68K)
1638 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1639 return -1;
1640#elif defined (ALPHA)
1641 return -1;
1642#elif defined (ARM)
1643 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001644#elif defined (MIPS)
1645 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001647 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001648 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001649#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001650 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1651 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001652#elif defined(HPPA)
1653 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1654 return -1;
1655 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001656#elif defined(SH)
1657 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1658 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001659#else
1660#error unknown architecture
1661#endif
1662 if (debug)
1663 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1664 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1665 if (errno) {
1666 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1667 return -1;
1668 }
1669 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1670 if (errno) {
1671 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1672 return -1;
1673 }
1674 tcp->flags |= TCB_BPTSET;
1675
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001676#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001677#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678#endif /* LINUX */
1679
1680#ifdef SUNOS4
1681#ifdef SPARC /* This code is slightly sparc specific */
1682
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001683 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684#define BPT 0x91d02001 /* ta 1 */
1685#define LOOP 0x10800000 /* ba 0 */
1686#define LOOPA 0x30800000 /* ba,a 0 */
1687#define NOP 0x01000000
1688#if LOOPA
1689 static int loopdeloop[1] = {LOOPA};
1690#else
1691 static int loopdeloop[2] = {LOOP, NOP};
1692#endif
1693
1694 if (tcp->flags & TCB_BPTSET) {
1695 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1696 return -1;
1697 }
1698 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1699 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1700 return -1;
1701 }
1702 tcp->baddr = regs.r_o7 + 8;
1703 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1704 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1705 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1706 return -1;
1707 }
1708
1709 /*
1710 * XXX - BRUTAL MODE ON
1711 * We cannot set a real BPT in the child, since it will not be
1712 * traced at the moment it will reach the trap and would probably
1713 * die with a core dump.
1714 * Thus, we are force our way in by taking out two instructions
1715 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1716 * generated by out PTRACE_ATTACH.
1717 * Of cause, if we evaporate ourselves in the middle of all this...
1718 */
1719 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1720 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1721 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1722 return -1;
1723 }
1724 tcp->flags |= TCB_BPTSET;
1725
1726#endif /* SPARC */
1727#endif /* SUNOS4 */
1728
1729 return 0;
1730}
1731
1732int
1733clearbpt(tcp)
1734struct tcb *tcp;
1735{
1736
1737#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001738#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001740#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001741 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001742#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001743 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001744#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001745 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001746#elif defined(HPPA)
1747 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001748#elif defined(SH)
1749 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001750#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001751
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001752#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753 /* Again, we borrow the SunOS breakpoint code. */
1754 if (!(tcp->flags & TCB_BPTSET)) {
1755 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1756 return -1;
1757 }
1758 errno = 0;
1759 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1760 if(errno) {
1761 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1762 return -1;
1763 }
1764 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001765#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001766 if (ia32) {
1767 unsigned long addr;
1768
1769 if (debug)
1770 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1771 if (!(tcp->flags & TCB_BPTSET)) {
1772 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1773 return -1;
1774 }
1775 errno = 0;
1776 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1777 if (errno) {
1778 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1779 return -1;
1780 }
1781 tcp->flags &= ~TCB_BPTSET;
1782
1783 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1784 return -1;
1785 if (addr != tcp->baddr) {
1786 /* The breakpoint has not been reached yet. */
1787 if (debug)
1788 fprintf(stderr,
1789 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1790 addr, tcp->baddr);
1791 return 0;
1792 }
1793 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001794 unsigned long addr, ipsr;
1795 pid_t pid;
1796
1797 pid = tcp->pid;
1798
1799 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1800 return -1;
1801 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1802 return -1;
1803
1804 /* restore original bundle: */
1805 errno = 0;
1806 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1807 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1808 if (errno) {
1809 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1810 return -1;
1811 }
1812
1813 /* restore original "ri" in ipsr: */
1814 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1815 errno = 0;
1816 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1817 if (errno) {
1818 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1819 return -1;
1820 }
1821
1822 tcp->flags &= ~TCB_BPTSET;
1823
1824 if (addr != (tcp->baddr & ~0x3)) {
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 addr, tcp->baddr);
1829 return 0;
1830 }
1831 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001832#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833
1834 if (debug)
1835 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1836 if (!(tcp->flags & TCB_BPTSET)) {
1837 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1838 return -1;
1839 }
1840 errno = 0;
1841 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1842 if (errno) {
1843 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1844 return -1;
1845 }
1846 tcp->flags &= ~TCB_BPTSET;
1847
1848#ifdef I386
1849 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1850 return -1;
1851 if (eip != tcp->baddr) {
1852 /* The breakpoint has not been reached yet. */
1853 if (debug)
1854 fprintf(stderr,
1855 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1856 eip, tcp->baddr);
1857 return 0;
1858 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001859#elif defined(X86_64)
1860 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1861 return -1;
1862 if (eip != tcp->baddr) {
1863 /* The breakpoint has not been reached yet. */
1864 if (debug)
1865 fprintf(stderr,
1866 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1867 eip, tcp->baddr);
1868 return 0;
1869 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001870#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001871 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001872 return -1;
1873 if (pc != tcp->baddr) {
1874 /* The breakpoint has not been reached yet. */
1875 if (debug)
1876 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1877 pc, tcp->baddr);
1878 return 0;
1879 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001880#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001881 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1882 return -1;
1883 if (pc != tcp->baddr) {
1884 /* The breakpoint has not been reached yet. */
1885 if (debug)
1886 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1887 pc, tcp->baddr);
1888 return 0;
1889 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001890#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001891 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1892 return -1;
1893 if (pc != tcp->baddr) {
1894 /* The breakpoint has not been reached yet. */
1895 if (debug)
1896 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1897 pc, tcp->baddr);
1898 return 0;
1899 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001900#elif defined(HPPA)
1901 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1902 return -1;
1903 iaoq &= ~0x03;
1904 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1905 /* The breakpoint has not been reached yet. */
1906 if (debug)
1907 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1908 iaoq, tcp->baddr);
1909 return 0;
1910 }
1911 iaoq = tcp->baddr | 3;
1912 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1913 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1914 * has no significant effect.
1915 */
1916 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1917 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001918#elif defined(SH)
1919 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1920 return -1;
1921 if (pc != tcp->baddr) {
1922 /* The breakpoint has not been reached yet. */
1923 if (debug)
1924 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1925 pc, tcp->baddr);
1926 return 0;
1927 }
1928
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001929#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001930#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001931#endif /* LINUX */
1932
1933#ifdef SUNOS4
1934#ifdef SPARC
1935
1936#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001937 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938#endif
1939
1940 if (!(tcp->flags & TCB_BPTSET)) {
1941 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1942 return -1;
1943 }
1944 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1945 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1946 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1947 return -1;
1948 }
1949 tcp->flags &= ~TCB_BPTSET;
1950
1951#if !LOOPA
1952 /*
1953 * Since we don't have a single instruction breakpoint, we may have
1954 * to adjust the program counter after removing the our `breakpoint'.
1955 */
1956 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1957 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1958 return -1;
1959 }
1960 if ((regs.r_pc < tcp->baddr) ||
1961 (regs.r_pc > tcp->baddr + 4)) {
1962 /* The breakpoint has not been reached yet */
1963 if (debug)
1964 fprintf(stderr,
1965 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1966 regs.r_pc, tcp->parent->baddr);
1967 return 0;
1968 }
1969 if (regs.r_pc != tcp->baddr)
1970 if (debug)
1971 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1972 regs.r_pc, tcp->baddr);
1973
1974 regs.r_pc = tcp->baddr;
1975 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1976 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1977 return -1;
1978 }
1979#endif /* LOOPA */
1980#endif /* SPARC */
1981#endif /* SUNOS4 */
1982
1983 return 0;
1984}
1985
Roland McGrathd81f1d92003-01-09 06:53:34 +00001986#endif
1987
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001988#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001989
1990#ifdef SUNOS4
1991
1992static int
1993getex(pid, hdr)
1994int pid;
1995struct exec *hdr;
1996{
1997 int n;
1998
1999 for (n = 0; n < sizeof *hdr; n += 4) {
2000 long res;
2001 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2002 return -1;
2003 memcpy(((char *) hdr) + n, &res, 4);
2004 }
2005 if (debug) {
2006 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2007 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2008 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2009 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2010 }
2011 return 0;
2012}
2013
2014int
2015fixvfork(tcp)
2016struct tcb *tcp;
2017{
2018 int pid = tcp->pid;
2019 /*
2020 * Change `vfork' in a freshly exec'ed dynamically linked
2021 * executable's (internal) symbol table to plain old `fork'
2022 */
2023
2024 struct exec hdr;
2025 struct link_dynamic dyn;
2026 struct link_dynamic_2 ld;
2027 char *strtab, *cp;
2028
2029 if (getex(pid, &hdr) < 0)
2030 return -1;
2031 if (!hdr.a_dynamic)
2032 return -1;
2033
2034 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2035 fprintf(stderr, "Cannot read DYNAMIC\n");
2036 return -1;
2037 }
2038 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2039 fprintf(stderr, "Cannot read link_dynamic_2\n");
2040 return -1;
2041 }
2042 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002043 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002044 return -1;
2045 }
2046 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2047 (int)ld.ld_symb_size, strtab) < 0)
2048 goto err;
2049
2050#if 0
2051 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2052 fprintf(stderr, "[symbol: %s]\n", cp);
2053 cp += strlen(cp)+1;
2054 }
2055 return 0;
2056#endif
2057 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2058 if (strcmp(cp, "_vfork") == 0) {
2059 if (debug)
2060 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2061 strcpy(cp, "_fork");
2062 break;
2063 }
2064 cp += strlen(cp)+1;
2065 }
2066 if (cp < strtab + ld.ld_symb_size)
2067 /*
2068 * Write entire symbol table back to avoid
2069 * memory alignment bugs in ptrace
2070 */
2071 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2072 (int)ld.ld_symb_size, strtab) < 0)
2073 goto err;
2074
2075 free(strtab);
2076 return 0;
2077
2078err:
2079 free(strtab);
2080 return -1;
2081}
2082
2083#endif /* SUNOS4 */