blob: 395492250a47d761cc2aa2cf810dc25ab99f8b84 [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 McGrath371ed8f2005-02-06 01:55:07 +0000427 if (addr == 0)
428 tprintf("NULL");
429 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000430 tprintf("%#lx", addr);
431 else {
432 path[n] = '\0';
433 string_quote(path);
434 }
435}
436
437void
438printstr(tcp, addr, len)
439struct tcb *tcp;
440long addr;
441int len;
442{
443 static unsigned char *str = NULL;
444 static char *outstr;
445 int i, n, c, usehex;
446 char *s, *outend;
447
448 if (!addr) {
449 tprintf("NULL");
450 return;
451 }
452 if (!str) {
453 if ((str = malloc(max_strlen)) == NULL
454 || (outstr = malloc(2*max_strlen)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000455 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000456 tprintf("%#lx", addr);
457 return;
458 }
459 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000460 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000461 if (len < 0) {
462 n = max_strlen;
463 if (umovestr(tcp, addr, n, (char *) str) < 0) {
464 tprintf("%#lx", addr);
465 return;
466 }
467 }
468 else {
469 n = MIN(len, max_strlen);
470 if (umoven(tcp, addr, n, (char *) str) < 0) {
471 tprintf("%#lx", addr);
472 return;
473 }
474 }
475
476 usehex = 0;
477 if (xflag > 1)
478 usehex = 1;
479 else if (xflag) {
480 for (i = 0; i < n; i++) {
481 c = str[i];
482 if (len < 0 && c == '\0')
483 break;
484 if (!isprint(c) && !isspace(c)) {
485 usehex = 1;
486 break;
487 }
488 }
489 }
490
491 s = outstr;
492 *s++ = '\"';
493
494 if (usehex) {
495 for (i = 0; i < n; i++) {
496 c = str[i];
497 if (len < 0 && c == '\0')
498 break;
499 sprintf(s, "\\x%02x", c);
500 s += 4;
501 if (s > outend)
502 break;
503 }
504 }
505 else {
506 for (i = 0; i < n; i++) {
507 c = str[i];
508 if (len < 0 && c == '\0')
509 break;
510 switch (c) {
511 case '\"': case '\'': case '\\':
512 *s++ = '\\'; *s++ = c; break;
513 case '\f':
514 *s++ = '\\'; *s++ = 'f'; break;
515 case '\n':
516 *s++ = '\\'; *s++ = 'n'; break;
517 case '\r':
518 *s++ = '\\'; *s++ = 'r'; break;
519 case '\t':
520 *s++ = '\\'; *s++ = 't'; break;
521 case '\v':
522 *s++ = '\\'; *s++ = 'v'; break;
523 default:
524 if (isprint(c))
525 *s++ = c;
526 else if (i < n - 1 && isdigit(str[i + 1])) {
527 sprintf(s, "\\%03o", c);
528 s += 4;
529 }
530 else {
531 sprintf(s, "\\%o", c);
532 s += strlen(s);
533 }
534 break;
535 }
536 if (s > outend)
537 break;
538 }
539 }
540
541 *s++ = '\"';
542 if (i < len || (len < 0 && (i == n || s > outend))) {
543 *s++ = '.'; *s++ = '.'; *s++ = '.';
544 }
545 *s = '\0';
546 tprintf("%s", outstr);
547}
548
John Hughes1d08dcf2001-07-10 13:48:44 +0000549#if HAVE_SYS_UIO_H
550void
551dumpiov(tcp, len, addr)
552struct tcb * tcp;
553int len;
554long addr;
555{
556 struct iovec *iov;
557 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000558 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000559
Roland McGrathaa524c82005-06-01 19:22:06 +0000560 size = sizeof(*iov) * (unsigned long) len;
561 if (size / sizeof(*iov) != len
562 || (iov = (struct iovec *) malloc(size)) == NULL) {
563 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000564 return;
565 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000566 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000567 for (i = 0; i < len; i++) {
568 /* include the buffer number to make it easy to
569 * match up the trace with the source */
570 tprintf(" * %lu bytes in buffer %d\n",
571 (unsigned long)iov[i].iov_len, i);
572 dumpstr(tcp, (long) iov[i].iov_base,
573 iov[i].iov_len);
574 }
575 }
576 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000577
John Hughes1d08dcf2001-07-10 13:48:44 +0000578}
579#endif
580
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000581void
582dumpstr(tcp, addr, len)
583struct tcb *tcp;
584long addr;
585int len;
586{
587 static int strsize = -1;
588 static unsigned char *str;
589 static char outstr[80];
590 char *s;
591 int i, j;
592
593 if (strsize < len) {
594 if (str)
595 free(str);
596 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000597 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598 return;
599 }
600 strsize = len;
601 }
602
603 if (umoven(tcp, addr, len, (char *) str) < 0)
604 return;
605
606 for (i = 0; i < len; i += 16) {
607 s = outstr;
608 sprintf(s, " | %05x ", i);
609 s += 9;
610 for (j = 0; j < 16; j++) {
611 if (j == 8)
612 *s++ = ' ';
613 if (i + j < len) {
614 sprintf(s, " %02x", str[i + j]);
615 s += 3;
616 }
617 else {
618 *s++ = ' '; *s++ = ' '; *s++ = ' ';
619 }
620 }
621 *s++ = ' '; *s++ = ' ';
622 for (j = 0; j < 16; j++) {
623 if (j == 8)
624 *s++ = ' ';
625 if (i + j < len) {
626 if (isprint(str[i + j]))
627 *s++ = str[i + j];
628 else
629 *s++ = '.';
630 }
631 else
632 *s++ = ' ';
633 }
634 tprintf("%s |\n", outstr);
635 }
636}
637
638#define PAGMASK (~(PAGSIZ - 1))
639/*
640 * move `len' bytes of data from process `pid'
641 * at address `addr' to our space at `laddr'
642 */
643int
644umoven(tcp, addr, len, laddr)
645struct tcb *tcp;
646long addr;
647int len;
648char *laddr;
649{
650
651#ifdef LINUX
652 int pid = tcp->pid;
653 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000654 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655 union {
656 long val;
657 char x[sizeof(long)];
658 } u;
659
660 if (addr & (sizeof(long) - 1)) {
661 /* addr not a multiple of sizeof(long) */
662 n = addr - (addr & -sizeof(long)); /* residue */
663 addr &= -sizeof(long); /* residue */
664 errno = 0;
665 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
666 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000667 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000668 /* Ran into 'end of memory' - stupid "printpath" */
669 return 0;
670 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000671 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000672 perror("ptrace: umoven");
673 return -1;
674 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000675 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
677 addr += sizeof(long), laddr += m, len -= m;
678 }
679 while (len) {
680 errno = 0;
681 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
682 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000683 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000684 /* Ran into 'end of memory' - stupid "printpath" */
685 return 0;
686 }
Roland McGrath4db26242003-01-30 20:15:19 +0000687 if (addr != 0)
688 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689 return -1;
690 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000691 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
693 addr += sizeof(long), laddr += m, len -= m;
694 }
695#endif /* LINUX */
696
697#ifdef SUNOS4
698 int pid = tcp->pid;
699#if 0
700 int n, m;
701 union {
702 long val;
703 char x[sizeof(long)];
704 } u;
705
706 if (addr & (sizeof(long) - 1)) {
707 /* addr not a multiple of sizeof(long) */
708 n = addr - (addr & -sizeof(long)); /* residue */
709 addr &= -sizeof(long); /* residue */
710 errno = 0;
711 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
712 if (errno) {
713 perror("umoven");
714 return -1;
715 }
716 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
717 addr += sizeof(long), laddr += m, len -= m;
718 }
719 while (len) {
720 errno = 0;
721 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
722 if (errno) {
723 perror("umoven");
724 return -1;
725 }
726 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
727 addr += sizeof(long), laddr += m, len -= m;
728 }
729#else /* !oldway */
730 int n;
731
732 while (len) {
733 n = MIN(len, PAGSIZ);
734 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
735 if (ptrace(PTRACE_READDATA, pid,
736 (char *) addr, len, laddr) < 0) {
737 perror("umoven: ptrace(PTRACE_READDATA, ...)");
738 abort();
739 return -1;
740 }
741 len -= n;
742 addr += n;
743 laddr += n;
744 }
745#endif /* !oldway */
746#endif /* SUNOS4 */
747
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000748#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000749#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000750 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000751#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000752 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000753#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000754 lseek(fd, addr, SEEK_SET);
755 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000757#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000758
759 return 0;
760}
761
762/*
763 * like `umove' but make the additional effort of looking
764 * for a terminating zero byte.
765 */
766int
767umovestr(tcp, addr, len, laddr)
768struct tcb *tcp;
769long addr;
770int len;
771char *laddr;
772{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000773#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000774#ifdef HAVE_MP_PROCFS
775 int fd = tcp->pfd_as;
776#else
777 int fd = tcp->pfd;
778#endif
779 /* Some systems (e.g. FreeBSD) can be upset if we read off the
780 end of valid memory, avoid this by trying to read up
781 to page boundaries. But we don't know what a page is (and
782 getpagesize(2) (if it exists) doesn't necessarily return
783 hardware page size). Assume all pages >= 1024 (a-historical
784 I know) */
785
786 int page = 1024; /* How to find this? */
787 int move = page - (addr & (page - 1));
788 int left = len;
789
790 lseek(fd, addr, SEEK_SET);
791
792 while (left) {
793 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000794 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000795 return left != len ? 0 : -1;
796 if (memchr (laddr, 0, move)) break;
797 left -= move;
798 laddr += move;
799 addr += move;
800 move = page;
801 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000802#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000803 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000804 int pid = tcp->pid;
805 int i, n, m;
806 union {
807 long val;
808 char x[sizeof(long)];
809 } u;
810
811 if (addr & (sizeof(long) - 1)) {
812 /* addr not a multiple of sizeof(long) */
813 n = addr - (addr & -sizeof(long)); /* residue */
814 addr &= -sizeof(long); /* residue */
815 errno = 0;
816 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
817 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000818 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000819 /* Ran into 'end of memory' - stupid "printpath" */
820 return 0;
821 }
822 perror("umovestr");
823 return -1;
824 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000825 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
827 while (n & (sizeof(long) - 1))
828 if (u.x[n++] == '\0')
829 return 0;
830 addr += sizeof(long), laddr += m, len -= m;
831 }
832 while (len) {
833 errno = 0;
834 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
835 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000836 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000837 /* Ran into 'end of memory' - stupid "printpath" */
838 return 0;
839 }
840 perror("umovestr");
841 return -1;
842 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000843 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000844 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
845 for (i = 0; i < sizeof(long); i++)
846 if (u.x[i] == '\0')
847 return 0;
848
849 addr += sizeof(long), laddr += m, len -= m;
850 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000851#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000852 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000853}
854
855#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000856#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000857#define PTRACE_WRITETEXT 101
858#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000859#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000860#endif /* LINUX */
861
862#ifdef SUNOS4
863
864static int
865uload(cmd, pid, addr, len, laddr)
866int cmd;
867int pid;
868long addr;
869int len;
870char *laddr;
871{
872#if 0
873 int n;
874
875 while (len) {
876 n = MIN(len, PAGSIZ);
877 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
878 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
879 perror("uload: ptrace(PTRACE_WRITE, ...)");
880 return -1;
881 }
882 len -= n;
883 addr += n;
884 laddr += n;
885 }
886#else
887 int peek, poke;
888 int n, m;
889 union {
890 long val;
891 char x[sizeof(long)];
892 } u;
893
894 if (cmd == PTRACE_WRITETEXT) {
895 peek = PTRACE_PEEKTEXT;
896 poke = PTRACE_POKETEXT;
897 }
898 else {
899 peek = PTRACE_PEEKDATA;
900 poke = PTRACE_POKEDATA;
901 }
902 if (addr & (sizeof(long) - 1)) {
903 /* addr not a multiple of sizeof(long) */
904 n = addr - (addr & -sizeof(long)); /* residue */
905 addr &= -sizeof(long);
906 errno = 0;
907 u.val = ptrace(peek, pid, (char *) addr, 0);
908 if (errno) {
909 perror("uload: POKE");
910 return -1;
911 }
912 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
913 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
914 perror("uload: POKE");
915 return -1;
916 }
917 addr += sizeof(long), laddr += m, len -= m;
918 }
919 while (len) {
920 if (len < sizeof(long))
921 u.val = ptrace(peek, pid, (char *) addr, 0);
922 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
923 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
924 perror("uload: POKE");
925 return -1;
926 }
927 addr += sizeof(long), laddr += m, len -= m;
928 }
929#endif
930 return 0;
931}
932
933int
934tload(pid, addr, len, laddr)
935int pid;
936int addr, len;
937char *laddr;
938{
939 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
940}
941
942int
943dload(pid, addr, len, laddr)
944int pid;
945int addr;
946int len;
947char *laddr;
948{
949 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
950}
951
952#endif /* SUNOS4 */
953
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000954#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955
956int
957upeek(pid, off, res)
958int pid;
959long off;
960long *res;
961{
962 long val;
963
964#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
965 {
966 static int is_sun4m = -1;
967 struct utsname name;
968
969 /* Round up the usual suspects. */
970 if (is_sun4m == -1) {
971 if (uname(&name) < 0) {
972 perror("upeek: uname?");
973 exit(1);
974 }
975 is_sun4m = strcmp(name.machine, "sun4m") == 0;
976 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000977 extern const struct xlat struct_user_offsets[];
978 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979
980 for (x = struct_user_offsets; x->str; x++)
981 x->val += 1024;
982 }
983 }
984 if (is_sun4m)
985 off += 1024;
986 }
987#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
988 errno = 0;
989 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
990 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000991 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000992 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000993 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 return -1;
995 }
996 *res = val;
997 return 0;
998}
999
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001000#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001001
Roland McGratha4d48532005-06-08 20:45:28 +00001002#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003long
1004getpc(tcp)
1005struct tcb *tcp;
1006{
1007
1008#ifdef LINUX
1009 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001010#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001011 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1012 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001013#elif defined(X86_64)
1014 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1015 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001016#elif defined(IA64)
1017 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1018 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001019#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001020 if (upeek(tcp->pid, 4*15, &pc) < 0)
1021 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001022#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001023 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001025#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001026 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1027 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001028#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1030 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001031#elif defined(MIPS)
1032 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1033 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001034#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001035 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1037 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001038 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001039#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001040 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001041 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001042#elif defined(HPPA)
1043 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1044 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001045#elif defined(SH)
1046 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1047 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001048#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001049 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1050 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001051#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 return pc;
1053#endif /* LINUX */
1054
1055#ifdef SUNOS4
1056 /*
1057 * Return current program counter for `pid'
1058 * Assumes PC is never 0xffffffff
1059 */
1060 struct regs regs;
1061
1062 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1063 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1064 return -1;
1065 }
1066 return regs.r_pc;
1067#endif /* SUNOS4 */
1068
1069#ifdef SVR4
1070 /* XXX */
1071 return 0;
1072#endif /* SVR4 */
1073
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001074#ifdef FREEBSD
1075 struct reg regs;
1076 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1077 return regs.r_eip;
1078#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079}
Roland McGratha4d48532005-06-08 20:45:28 +00001080#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001081
1082void
1083printcall(tcp)
1084struct tcb *tcp;
1085{
Roland McGrath7a918832005-02-02 20:55:23 +00001086#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1087 sizeof(long) == 8 ? "[????????????????] " : \
1088 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001089
1090#ifdef LINUX
1091#ifdef I386
1092 long eip;
1093
1094 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001095 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001096 return;
1097 }
1098 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001099
1100#elif defined(S390) || defined(S390X)
1101 long psw;
1102 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001103 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001104 return;
1105 }
1106#ifdef S390
1107 tprintf("[%08lx] ", psw);
1108#elif S390X
1109 tprintf("[%16lx] ", psw);
1110#endif
1111
Michal Ludvig0e035502002-09-23 15:41:01 +00001112#elif defined(X86_64)
1113 long rip;
1114
1115 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001116 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001117 return;
1118 }
1119 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001120#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001121 long ip;
1122
1123 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001124 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001125 return;
1126 }
1127 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001128#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129 long pc;
1130
Roland McGratheb285352003-01-14 09:59:00 +00001131 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 tprintf ("[????????] ");
1133 return;
1134 }
1135 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001136#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137 long pc;
1138
1139 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1140 tprintf ("[????????] ");
1141 return;
1142 }
1143 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001144#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001145 long pc;
1146
1147 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001148 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149 return;
1150 }
1151 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001152#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001153 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001155 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 return;
1157 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001158 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001159#elif defined(HPPA)
1160 long pc;
1161
1162 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1163 tprintf ("[????????] ");
1164 return;
1165 }
1166 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001167#elif defined(MIPS)
1168 long pc;
1169
1170 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1171 tprintf ("[????????] ");
1172 return;
1173 }
1174 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001175#elif defined(SH)
1176 long pc;
1177
1178 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1179 tprintf ("[????????] ");
1180 return;
1181 }
1182 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001183#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001184 long pc;
1185
1186 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001187 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001188 return;
1189 }
1190 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001191#elif defined(ARM)
1192 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001193
Roland McGrathef388682003-06-03 23:28:59 +00001194 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001195 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001196 return;
1197 }
1198 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001199#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200#endif /* LINUX */
1201
1202#ifdef SUNOS4
1203 struct regs regs;
1204
1205 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1206 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001207 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208 return;
1209 }
1210 tprintf("[%08x] ", regs.r_o7);
1211#endif /* SUNOS4 */
1212
1213#ifdef SVR4
1214 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001215 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216#endif
1217
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001218#ifdef FREEBSD
1219 struct reg regs;
1220 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1221 tprintf("[%08x] ", regs.r_eip);
1222#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223}
1224
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001225#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226
Roland McGrathd81f1d92003-01-09 06:53:34 +00001227#if defined LINUX
1228
1229#include <sys/syscall.h>
1230#ifndef CLONE_PTRACE
1231# define CLONE_PTRACE 0x00002000
1232#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001233#ifndef CLONE_STOPPED
1234# define CLONE_STOPPED 0x02000000
1235#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001236
1237#ifdef IA64
1238
Roland McGrath08267b82004-02-20 22:56:43 +00001239/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1240 subsystem has them for x86... */
1241#define SYS_fork 2
1242#define SYS_vfork 190
1243
Roland McGrathd81f1d92003-01-09 06:53:34 +00001244typedef unsigned long *arg_setup_state;
1245
1246static int
1247arg_setup(struct tcb *tcp, arg_setup_state *state)
1248{
1249 unsigned long *bsp, cfm, sof, sol;
1250
Roland McGrath08267b82004-02-20 22:56:43 +00001251 if (ia32)
1252 return 0;
1253
Roland McGrathd81f1d92003-01-09 06:53:34 +00001254 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1255 return -1;
1256 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1257 return -1;
1258
1259 sof = (cfm >> 0) & 0x7f;
1260 sol = (cfm >> 7) & 0x7f;
1261 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1262
1263 *state = bsp;
1264 return 0;
1265}
1266
1267# define arg_finish_change(tcp, state) 0
1268
1269#ifdef SYS_fork
1270static int
1271get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1272{
Roland McGrath08267b82004-02-20 22:56:43 +00001273 int ret;
1274
1275 if (ia32)
1276 ret = upeek (tcp->pid, PT_R11, valp);
1277 else
1278 ret = umoven (tcp,
1279 (unsigned long) ia64_rse_skip_regs(*state, 0),
1280 sizeof(long), (void *) valp);
1281 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001282}
1283
1284static int
1285get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1286{
Roland McGrath08267b82004-02-20 22:56:43 +00001287 int ret;
1288
1289 if (ia32)
1290 ret = upeek (tcp->pid, PT_R9, valp);
1291 else
1292 ret = umoven (tcp,
1293 (unsigned long) ia64_rse_skip_regs(*state, 1),
1294 sizeof(long), (void *) valp);
1295 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001296}
1297#endif
1298
1299static int
1300set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1301{
Roland McGrath08267b82004-02-20 22:56:43 +00001302 int req = PTRACE_POKEDATA;
1303 void *ap;
1304
1305 if (ia32) {
1306 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1307 req = PTRACE_POKEUSER;
1308 } else
1309 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001310 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001311 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001312 return errno ? -1 : 0;
1313}
1314
1315static int
1316set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1317{
Roland McGrath08267b82004-02-20 22:56:43 +00001318 int req = PTRACE_POKEDATA;
1319 void *ap;
1320
1321 if (ia32) {
1322 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1323 req = PTRACE_POKEUSER;
1324 } else
1325 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001326 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001327 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001328 return errno ? -1 : 0;
1329}
1330
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001331#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001332
1333typedef struct regs arg_setup_state;
1334
1335# define arg_setup(tcp, state) \
1336 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1337# define arg_finish_change(tcp, state) \
1338 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1339
1340# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1341# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1342# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1343# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001344# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001345
1346#else
1347
1348# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001349/* Note: this is only true for the `clone' system call, which handles
1350 arguments specially. We could as well say that its first two arguments
1351 are swapped relative to other architectures, but that would just be
1352 another #ifdef in the calls. */
1353# define arg0_offset PT_GPR3
1354# define arg1_offset PT_ORIGGPR2
1355# define restore_arg0(tcp, state, val) ((void) (state), 0)
1356# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001357# define arg0_index 1
1358# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001359# elif defined (ALPHA) || defined (MIPS)
1360# define arg0_offset REG_A0
1361# define arg1_offset (REG_A0+1)
1362# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001363# define arg0_offset (sizeof(unsigned long)*PT_R3)
1364# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001365# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001366# elif defined (HPPA)
1367# define arg0_offset PT_GR26
1368# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001369# elif defined (X86_64)
1370# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1371# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001372# elif defined (SH)
1373# define arg0_offset (4*(REG_REG0+4))
1374# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001375# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001376 /* ABI defines arg0 & 1 in r2 & r3 */
1377# define arg0_offset (REG_OFFSET+16)
1378# define arg1_offset (REG_OFFSET+24)
1379# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001380# else
1381# define arg0_offset 0
1382# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001383# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001384# define restore_arg0(tcp, state, val) 0
1385# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001386# endif
1387
1388typedef int arg_setup_state;
1389
1390# define arg_setup(tcp, state) (0)
1391# define arg_finish_change(tcp, state) 0
1392# define get_arg0(tcp, cookie, valp) \
1393 (upeek ((tcp)->pid, arg0_offset, (valp)))
1394# define get_arg1(tcp, cookie, valp) \
1395 (upeek ((tcp)->pid, arg1_offset, (valp)))
1396
1397static int
1398set_arg0 (struct tcb *tcp, void *cookie, long val)
1399{
Roland McGrathca85b972005-06-07 23:22:08 +00001400 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401}
1402
1403static int
1404set_arg1 (struct tcb *tcp, void *cookie, long val)
1405{
1406 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1407}
1408
1409#endif
1410
Roland McGrathe1df47f2003-01-14 09:46:15 +00001411#ifndef restore_arg0
1412# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1413#endif
1414#ifndef restore_arg1
1415# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1416#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001417
Roland McGrath90d0afd2004-03-01 21:05:16 +00001418#ifndef arg0_index
1419# define arg0_index 0
1420# define arg1_index 1
1421#endif
1422
Roland McGrathd81f1d92003-01-09 06:53:34 +00001423int
1424setbpt(tcp)
1425struct tcb *tcp;
1426{
1427 extern int change_syscall(struct tcb *, int);
1428 arg_setup_state state;
1429
1430 if (tcp->flags & TCB_BPTSET) {
1431 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1432 return -1;
1433 }
1434
Roland McGrath76989d72005-06-07 23:21:31 +00001435 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001436#ifdef SYS_vfork
1437 case SYS_vfork:
1438#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001439#ifdef SYS_fork
1440 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001441#endif
1442#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001443 if (arg_setup (tcp, &state) < 0
1444 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1445 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1446 || change_syscall(tcp, SYS_clone) < 0
1447 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1448 || set_arg1 (tcp, &state, 0) < 0
1449 || arg_finish_change (tcp, &state) < 0)
1450 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001451 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1452 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001453 tcp->flags |= TCB_BPTSET;
1454 return 0;
1455#endif
1456
1457 case SYS_clone:
1458#ifdef SYS_clone2
1459 case SYS_clone2:
1460#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001461 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001462 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001463 || set_arg0 (tcp, &state,
1464 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001465 || arg_finish_change (tcp, &state) < 0))
1466 return -1;
1467 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001468 tcp->inst[0] = tcp->u_arg[arg0_index];
1469 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001470 return 0;
1471
1472 default:
1473 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1474 tcp->scno, tcp->pid);
1475 break;
1476 }
1477
1478 return -1;
1479}
1480
1481int
1482clearbpt(tcp)
1483struct tcb *tcp;
1484{
1485 arg_setup_state state;
1486 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001487 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1488 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001489 || arg_finish_change (tcp, &state))
1490 return -1;
1491 tcp->flags &= ~TCB_BPTSET;
1492 return 0;
1493}
1494
1495#else
1496
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001497int
1498setbpt(tcp)
1499struct tcb *tcp;
1500{
1501
1502#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001503#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504 /* We simply use the SunOS breakpoint code. */
1505
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001506 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001507 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001508#define LOOPA 0x30800000 /* ba,a 0 */
1509
1510 if (tcp->flags & TCB_BPTSET) {
1511 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1512 return -1;
1513 }
1514 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1515 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1516 return -1;
1517 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001518 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519 errno = 0;
1520 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1521 if(errno) {
1522 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1523 return -1;
1524 }
1525
1526 /*
1527 * XXX - BRUTAL MODE ON
1528 * We cannot set a real BPT in the child, since it will not be
1529 * traced at the moment it will reach the trap and would probably
1530 * die with a core dump.
1531 * Thus, we are force our way in by taking out two instructions
1532 * and insert an eternal loop instead, in expectance of the SIGSTOP
1533 * generated by out PTRACE_ATTACH.
1534 * Of cause, if we evaporate ourselves in the middle of all this...
1535 */
1536 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001537 inst = LOOPA;
1538#if defined (SPARC64)
1539 inst <<= 32;
1540 inst |= (tcp->inst[0] & 0xffffffffUL);
1541#endif
1542 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001543 if(errno) {
1544 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1545 return -1;
1546 }
1547 tcp->flags |= TCB_BPTSET;
1548
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001549#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001550#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001551 if (ia32) {
1552# define LOOP 0x0000feeb
1553 if (tcp->flags & TCB_BPTSET) {
1554 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1555 tcp->pid);
1556 return -1;
1557 }
1558 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1559 return -1;
1560 if (debug)
1561 fprintf(stderr, "[%d] setting bpt at %lx\n",
1562 tcp->pid, tcp->baddr);
1563 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1564 (char *) tcp->baddr, 0);
1565 if (errno) {
1566 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1567 return -1;
1568 }
1569 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1570 if (errno) {
1571 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1572 return -1;
1573 }
1574 tcp->flags |= TCB_BPTSET;
1575 } else {
1576 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001577 * Our strategy here is to replace the bundle that
1578 * contained the clone() syscall with a bundle of the
1579 * form:
1580 *
1581 * { 1: br 1b; br 1b; br 1b }
1582 *
1583 * This ensures that the newly forked child will loop
1584 * endlessly until we've got a chance to attach to it.
1585 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001586# define LOOP0 0x0000100000000017
1587# define LOOP1 0x4000000000200000
1588 unsigned long addr, ipsr;
1589 pid_t pid;
1590
1591 pid = tcp->pid;
1592 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1593 return -1;
1594 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1595 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001596 /* store "ri" in low two bits */
1597 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001598
1599 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001600 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1601 0);
1602 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1603 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001604 if (errno) {
1605 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1606 return -1;
1607 }
1608
1609 errno = 0;
1610 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1611 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1612 if (errno) {
1613 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1614 return -1;
1615 }
1616 tcp->flags |= TCB_BPTSET;
1617 }
1618#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619
Michal Ludvig0e035502002-09-23 15:41:01 +00001620#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621#define LOOP 0x0000feeb
1622#elif defined (M68K)
1623#define LOOP 0x60fe0000
1624#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001625#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001627#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001628#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001629#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001630#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001631#define LOOP 0x1000ffff
1632#elif defined(S390)
1633#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001634#elif defined(S390X)
1635#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001636#elif defined(HPPA)
1637#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001638#elif defined(SH)
1639#ifdef __LITTLE_ENDIAN__
1640#define LOOP 0x0000affe
1641#else
1642#define LOOP 0xfeaf0000
1643#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644#else
1645#error unknown architecture
1646#endif
1647
1648 if (tcp->flags & TCB_BPTSET) {
1649 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1650 return -1;
1651 }
1652#if defined (I386)
1653 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1654 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001655#elif defined (X86_64)
1656 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1657 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658#elif defined (M68K)
1659 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1660 return -1;
1661#elif defined (ALPHA)
1662 return -1;
1663#elif defined (ARM)
1664 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001665#elif defined (MIPS)
1666 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001667#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001668 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001669 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001670#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001671 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1672 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001673#elif defined(HPPA)
1674 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1675 return -1;
1676 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001677#elif defined(SH)
1678 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1679 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680#else
1681#error unknown architecture
1682#endif
1683 if (debug)
1684 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1685 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1686 if (errno) {
1687 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1688 return -1;
1689 }
1690 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1691 if (errno) {
1692 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1693 return -1;
1694 }
1695 tcp->flags |= TCB_BPTSET;
1696
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001697#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001698#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699#endif /* LINUX */
1700
1701#ifdef SUNOS4
1702#ifdef SPARC /* This code is slightly sparc specific */
1703
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001704 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705#define BPT 0x91d02001 /* ta 1 */
1706#define LOOP 0x10800000 /* ba 0 */
1707#define LOOPA 0x30800000 /* ba,a 0 */
1708#define NOP 0x01000000
1709#if LOOPA
1710 static int loopdeloop[1] = {LOOPA};
1711#else
1712 static int loopdeloop[2] = {LOOP, NOP};
1713#endif
1714
1715 if (tcp->flags & TCB_BPTSET) {
1716 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1717 return -1;
1718 }
1719 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1720 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1721 return -1;
1722 }
1723 tcp->baddr = regs.r_o7 + 8;
1724 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1725 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1726 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1727 return -1;
1728 }
1729
1730 /*
1731 * XXX - BRUTAL MODE ON
1732 * We cannot set a real BPT in the child, since it will not be
1733 * traced at the moment it will reach the trap and would probably
1734 * die with a core dump.
1735 * Thus, we are force our way in by taking out two instructions
1736 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1737 * generated by out PTRACE_ATTACH.
1738 * Of cause, if we evaporate ourselves in the middle of all this...
1739 */
1740 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1741 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1742 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1743 return -1;
1744 }
1745 tcp->flags |= TCB_BPTSET;
1746
1747#endif /* SPARC */
1748#endif /* SUNOS4 */
1749
1750 return 0;
1751}
1752
1753int
1754clearbpt(tcp)
1755struct tcb *tcp;
1756{
1757
1758#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001759#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001761#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001763#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001764 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001765#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001767#elif defined(HPPA)
1768 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001769#elif defined(SH)
1770 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001771#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001773#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774 /* Again, we borrow the SunOS breakpoint code. */
1775 if (!(tcp->flags & TCB_BPTSET)) {
1776 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1777 return -1;
1778 }
1779 errno = 0;
1780 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1781 if(errno) {
1782 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1783 return -1;
1784 }
1785 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001786#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001787 if (ia32) {
1788 unsigned long addr;
1789
1790 if (debug)
1791 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1792 if (!(tcp->flags & TCB_BPTSET)) {
1793 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1794 return -1;
1795 }
1796 errno = 0;
1797 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1798 if (errno) {
1799 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1800 return -1;
1801 }
1802 tcp->flags &= ~TCB_BPTSET;
1803
1804 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1805 return -1;
1806 if (addr != tcp->baddr) {
1807 /* The breakpoint has not been reached yet. */
1808 if (debug)
1809 fprintf(stderr,
1810 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1811 addr, tcp->baddr);
1812 return 0;
1813 }
1814 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001815 unsigned long addr, ipsr;
1816 pid_t pid;
1817
1818 pid = tcp->pid;
1819
1820 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1821 return -1;
1822 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1823 return -1;
1824
1825 /* restore original bundle: */
1826 errno = 0;
1827 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1828 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1829 if (errno) {
1830 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1831 return -1;
1832 }
1833
1834 /* restore original "ri" in ipsr: */
1835 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1836 errno = 0;
1837 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1838 if (errno) {
1839 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1840 return -1;
1841 }
1842
1843 tcp->flags &= ~TCB_BPTSET;
1844
1845 if (addr != (tcp->baddr & ~0x3)) {
1846 /* the breakpoint has not been reached yet. */
1847 if (debug)
1848 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1849 addr, tcp->baddr);
1850 return 0;
1851 }
1852 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001853#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001854
1855 if (debug)
1856 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1857 if (!(tcp->flags & TCB_BPTSET)) {
1858 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1859 return -1;
1860 }
1861 errno = 0;
1862 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1863 if (errno) {
1864 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1865 return -1;
1866 }
1867 tcp->flags &= ~TCB_BPTSET;
1868
1869#ifdef I386
1870 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1871 return -1;
1872 if (eip != tcp->baddr) {
1873 /* The breakpoint has not been reached yet. */
1874 if (debug)
1875 fprintf(stderr,
1876 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1877 eip, tcp->baddr);
1878 return 0;
1879 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001880#elif defined(X86_64)
1881 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1882 return -1;
1883 if (eip != tcp->baddr) {
1884 /* The breakpoint has not been reached yet. */
1885 if (debug)
1886 fprintf(stderr,
1887 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1888 eip, tcp->baddr);
1889 return 0;
1890 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001891#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001892 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001893 return -1;
1894 if (pc != tcp->baddr) {
1895 /* The breakpoint has not been reached yet. */
1896 if (debug)
1897 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1898 pc, tcp->baddr);
1899 return 0;
1900 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001901#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001902 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1903 return -1;
1904 if (pc != tcp->baddr) {
1905 /* The breakpoint has not been reached yet. */
1906 if (debug)
1907 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1908 pc, tcp->baddr);
1909 return 0;
1910 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001911#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1913 return -1;
1914 if (pc != tcp->baddr) {
1915 /* The breakpoint has not been reached yet. */
1916 if (debug)
1917 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1918 pc, tcp->baddr);
1919 return 0;
1920 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001921#elif defined(HPPA)
1922 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1923 return -1;
1924 iaoq &= ~0x03;
1925 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1926 /* The breakpoint has not been reached yet. */
1927 if (debug)
1928 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1929 iaoq, tcp->baddr);
1930 return 0;
1931 }
1932 iaoq = tcp->baddr | 3;
1933 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1934 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1935 * has no significant effect.
1936 */
1937 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1938 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001939#elif defined(SH)
1940 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1941 return -1;
1942 if (pc != tcp->baddr) {
1943 /* The breakpoint has not been reached yet. */
1944 if (debug)
1945 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1946 pc, tcp->baddr);
1947 return 0;
1948 }
1949
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001950#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001951#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001952#endif /* LINUX */
1953
1954#ifdef SUNOS4
1955#ifdef SPARC
1956
1957#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001958 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001959#endif
1960
1961 if (!(tcp->flags & TCB_BPTSET)) {
1962 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1963 return -1;
1964 }
1965 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1966 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1967 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1968 return -1;
1969 }
1970 tcp->flags &= ~TCB_BPTSET;
1971
1972#if !LOOPA
1973 /*
1974 * Since we don't have a single instruction breakpoint, we may have
1975 * to adjust the program counter after removing the our `breakpoint'.
1976 */
1977 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1978 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1979 return -1;
1980 }
1981 if ((regs.r_pc < tcp->baddr) ||
1982 (regs.r_pc > tcp->baddr + 4)) {
1983 /* The breakpoint has not been reached yet */
1984 if (debug)
1985 fprintf(stderr,
1986 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1987 regs.r_pc, tcp->parent->baddr);
1988 return 0;
1989 }
1990 if (regs.r_pc != tcp->baddr)
1991 if (debug)
1992 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1993 regs.r_pc, tcp->baddr);
1994
1995 regs.r_pc = tcp->baddr;
1996 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1997 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1998 return -1;
1999 }
2000#endif /* LOOPA */
2001#endif /* SPARC */
2002#endif /* SUNOS4 */
2003
2004 return 0;
2005}
2006
Roland McGrathd81f1d92003-01-09 06:53:34 +00002007#endif
2008
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002009#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010
2011#ifdef SUNOS4
2012
2013static int
2014getex(pid, hdr)
2015int pid;
2016struct exec *hdr;
2017{
2018 int n;
2019
2020 for (n = 0; n < sizeof *hdr; n += 4) {
2021 long res;
2022 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2023 return -1;
2024 memcpy(((char *) hdr) + n, &res, 4);
2025 }
2026 if (debug) {
2027 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2028 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2029 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2030 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2031 }
2032 return 0;
2033}
2034
2035int
2036fixvfork(tcp)
2037struct tcb *tcp;
2038{
2039 int pid = tcp->pid;
2040 /*
2041 * Change `vfork' in a freshly exec'ed dynamically linked
2042 * executable's (internal) symbol table to plain old `fork'
2043 */
2044
2045 struct exec hdr;
2046 struct link_dynamic dyn;
2047 struct link_dynamic_2 ld;
2048 char *strtab, *cp;
2049
2050 if (getex(pid, &hdr) < 0)
2051 return -1;
2052 if (!hdr.a_dynamic)
2053 return -1;
2054
2055 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2056 fprintf(stderr, "Cannot read DYNAMIC\n");
2057 return -1;
2058 }
2059 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2060 fprintf(stderr, "Cannot read link_dynamic_2\n");
2061 return -1;
2062 }
2063 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002064 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002065 return -1;
2066 }
2067 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2068 (int)ld.ld_symb_size, strtab) < 0)
2069 goto err;
2070
2071#if 0
2072 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2073 fprintf(stderr, "[symbol: %s]\n", cp);
2074 cp += strlen(cp)+1;
2075 }
2076 return 0;
2077#endif
2078 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2079 if (strcmp(cp, "_vfork") == 0) {
2080 if (debug)
2081 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2082 strcpy(cp, "_fork");
2083 break;
2084 }
2085 cp += strlen(cp)+1;
2086 }
2087 if (cp < strtab + ld.ld_symb_size)
2088 /*
2089 * Write entire symbol table back to avoid
2090 * memory alignment bugs in ptrace
2091 */
2092 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2093 (int)ld.ld_symb_size, strtab) < 0)
2094 goto err;
2095
2096 free(strtab);
2097 return 0;
2098
2099err:
2100 free(strtab);
2101 return -1;
2102}
2103
2104#endif /* SUNOS4 */