blob: 4f2dd5e46c69110c3d6f767a6cae3772d41a3a5a [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
151void
152tv_tv(tv, a, b)
153struct timeval *tv;
154int a;
155int b;
156{
157 tv->tv_sec = a;
158 tv->tv_usec = b;
159}
160
161int
162tv_nz(a)
163struct timeval *a;
164{
165 return a->tv_sec || a->tv_usec;
166}
167
168int
169tv_cmp(a, b)
170struct timeval *a, *b;
171{
172 if (a->tv_sec < b->tv_sec
173 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
174 return -1;
175 if (a->tv_sec > b->tv_sec
176 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
177 return 1;
178 return 0;
179}
180
181double
182tv_float(tv)
183struct timeval *tv;
184{
185 return tv->tv_sec + tv->tv_usec/1000000.0;
186}
187
188void
189tv_add(tv, a, b)
190struct timeval *tv, *a, *b;
191{
192 tv->tv_sec = a->tv_sec + b->tv_sec;
193 tv->tv_usec = a->tv_usec + b->tv_usec;
194 if (tv->tv_usec > 1000000) {
195 tv->tv_sec++;
196 tv->tv_usec -= 1000000;
197 }
198}
199
200void
201tv_sub(tv, a, b)
202struct timeval *tv, *a, *b;
203{
204 tv->tv_sec = a->tv_sec - b->tv_sec;
205 tv->tv_usec = a->tv_usec - b->tv_usec;
206 if (((long) tv->tv_usec) < 0) {
207 tv->tv_sec--;
208 tv->tv_usec += 1000000;
209 }
210}
211
212void
213tv_div(tv, a, n)
214struct timeval *tv, *a;
215int n;
216{
217 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219 tv->tv_usec %= 1000000;
220}
221
222void
223tv_mul(tv, a, n)
224struct timeval *tv, *a;
225int n;
226{
227 tv->tv_usec = a->tv_usec * n;
228 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229 tv->tv_usec %= 1000000;
230}
231
232char *
233xlookup(xlat, val)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000234const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235int val;
236{
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
239 return xlat->str;
240 return NULL;
241}
242
243/*
244 * Print entry in struct xlat table, if there.
245 */
246void
247printxval(xlat, val, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000248const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000249int val;
Roland McGrathb2dee132005-06-01 19:02:36 +0000250const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251{
252 char *str = xlookup(xlat, val);
253
254 if (str)
255 tprintf("%s", str);
256 else
257 tprintf("%#x /* %s */", val, dflt);
258}
259
260/*
261 * Interpret `xlat' as an array of flags
262 * print the entries whose bits are on in `flags'
263 * return # of flags printed.
264 */
265int
266addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000267const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000268int flags;
269{
270 int n;
271
272 for (n = 0; xlat->str; xlat++) {
273 if (xlat->val && (flags & xlat->val) == xlat->val) {
274 tprintf("|%s", xlat->str);
275 flags &= ~xlat->val;
276 n++;
277 }
278 }
279 if (flags) {
280 tprintf("|%#x", flags);
281 n++;
282 }
283 return n;
284}
285
286int
Roland McGrathb2dee132005-06-01 19:02:36 +0000287printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000288const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000289int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000290const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000291{
292 int n;
293 char *sep;
294
295 if (flags == 0 && xlat->val == 0) {
296 tprintf("%s", xlat->str);
297 return 1;
298 }
299
300 sep = "";
301 for (n = 0; xlat->str; xlat++) {
302 if (xlat->val && (flags & xlat->val) == xlat->val) {
303 tprintf("%s%s", sep, xlat->str);
304 flags &= ~xlat->val;
305 sep = "|";
306 n++;
307 }
308 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000309
310 if (n) {
311 if (flags) {
312 tprintf("%s%#x", sep, flags);
313 n++;
314 }
315 } else {
316 if (flags) {
317 tprintf("%#x", flags);
318 if (dflt)
319 tprintf(" /* %s */", dflt);
320 } else {
321 if (dflt)
322 tprintf("0");
323 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000325
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326 return n;
327}
328
329void
330printnum(tcp, addr, fmt)
331struct tcb *tcp;
332long addr;
333char *fmt;
334{
Roland McGratheb285352003-01-14 09:59:00 +0000335 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000336
337 if (!addr) {
338 tprintf("NULL");
339 return;
340 }
341 if (umove(tcp, addr, &num) < 0) {
342 tprintf("%#lx", addr);
343 return;
344 }
345 tprintf("[");
346 tprintf(fmt, num);
347 tprintf("]");
348}
349
Roland McGrath6bc12202003-11-13 22:32:27 +0000350void
351printuid(text, uid)
352const char *text;
353unsigned long uid;
354{
355 tprintf("%s", text);
356 tprintf((uid == -1) ? "%ld" : "%lu", uid);
357}
358
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000359static char path[MAXPATHLEN + 1];
360
361void
362string_quote(str)
363char *str;
364{
365 char buf[2 * MAXPATHLEN + 1];
366 char *s;
367
368 if (!strpbrk(str, "\"\'\\")) {
369 tprintf("\"%s\"", str);
370 return;
371 }
372 for (s = buf; *str; str++) {
373 switch (*str) {
374 case '\"': case '\'': case '\\':
375 *s++ = '\\'; *s++ = *str; break;
376 default:
377 *s++ = *str; break;
378 }
379 }
380 *s = '\0';
381 tprintf("\"%s\"", buf);
382}
383
384void
385printpath(tcp, addr)
386struct tcb *tcp;
387long addr;
388{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000389 if (addr == 0)
390 tprintf("NULL");
391 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000392 tprintf("%#lx", addr);
393 else
394 string_quote(path);
395 return;
396}
397
398void
399printpathn(tcp, addr, n)
400struct tcb *tcp;
401long addr;
402int n;
403{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000404 if (addr == 0)
405 tprintf("NULL");
406 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000407 tprintf("%#lx", addr);
408 else {
409 path[n] = '\0';
410 string_quote(path);
411 }
412}
413
414void
415printstr(tcp, addr, len)
416struct tcb *tcp;
417long addr;
418int len;
419{
420 static unsigned char *str = NULL;
421 static char *outstr;
422 int i, n, c, usehex;
423 char *s, *outend;
424
425 if (!addr) {
426 tprintf("NULL");
427 return;
428 }
429 if (!str) {
430 if ((str = malloc(max_strlen)) == NULL
431 || (outstr = malloc(2*max_strlen)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000432 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433 tprintf("%#lx", addr);
434 return;
435 }
436 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000437 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000438 if (len < 0) {
439 n = max_strlen;
440 if (umovestr(tcp, addr, n, (char *) str) < 0) {
441 tprintf("%#lx", addr);
442 return;
443 }
444 }
445 else {
446 n = MIN(len, max_strlen);
447 if (umoven(tcp, addr, n, (char *) str) < 0) {
448 tprintf("%#lx", addr);
449 return;
450 }
451 }
452
453 usehex = 0;
454 if (xflag > 1)
455 usehex = 1;
456 else if (xflag) {
457 for (i = 0; i < n; i++) {
458 c = str[i];
459 if (len < 0 && c == '\0')
460 break;
461 if (!isprint(c) && !isspace(c)) {
462 usehex = 1;
463 break;
464 }
465 }
466 }
467
468 s = outstr;
469 *s++ = '\"';
470
471 if (usehex) {
472 for (i = 0; i < n; i++) {
473 c = str[i];
474 if (len < 0 && c == '\0')
475 break;
476 sprintf(s, "\\x%02x", c);
477 s += 4;
478 if (s > outend)
479 break;
480 }
481 }
482 else {
483 for (i = 0; i < n; i++) {
484 c = str[i];
485 if (len < 0 && c == '\0')
486 break;
487 switch (c) {
488 case '\"': case '\'': case '\\':
489 *s++ = '\\'; *s++ = c; break;
490 case '\f':
491 *s++ = '\\'; *s++ = 'f'; break;
492 case '\n':
493 *s++ = '\\'; *s++ = 'n'; break;
494 case '\r':
495 *s++ = '\\'; *s++ = 'r'; break;
496 case '\t':
497 *s++ = '\\'; *s++ = 't'; break;
498 case '\v':
499 *s++ = '\\'; *s++ = 'v'; break;
500 default:
501 if (isprint(c))
502 *s++ = c;
503 else if (i < n - 1 && isdigit(str[i + 1])) {
504 sprintf(s, "\\%03o", c);
505 s += 4;
506 }
507 else {
508 sprintf(s, "\\%o", c);
509 s += strlen(s);
510 }
511 break;
512 }
513 if (s > outend)
514 break;
515 }
516 }
517
518 *s++ = '\"';
519 if (i < len || (len < 0 && (i == n || s > outend))) {
520 *s++ = '.'; *s++ = '.'; *s++ = '.';
521 }
522 *s = '\0';
523 tprintf("%s", outstr);
524}
525
John Hughes1d08dcf2001-07-10 13:48:44 +0000526#if HAVE_SYS_UIO_H
527void
528dumpiov(tcp, len, addr)
529struct tcb * tcp;
530int len;
531long addr;
532{
533 struct iovec *iov;
534 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000535 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000536
Roland McGrathaa524c82005-06-01 19:22:06 +0000537 size = sizeof(*iov) * (unsigned long) len;
538 if (size / sizeof(*iov) != len
539 || (iov = (struct iovec *) malloc(size)) == NULL) {
540 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000541 return;
542 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000543 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000544 for (i = 0; i < len; i++) {
545 /* include the buffer number to make it easy to
546 * match up the trace with the source */
547 tprintf(" * %lu bytes in buffer %d\n",
548 (unsigned long)iov[i].iov_len, i);
549 dumpstr(tcp, (long) iov[i].iov_base,
550 iov[i].iov_len);
551 }
552 }
553 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000554
John Hughes1d08dcf2001-07-10 13:48:44 +0000555}
556#endif
557
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558void
559dumpstr(tcp, addr, len)
560struct tcb *tcp;
561long addr;
562int len;
563{
564 static int strsize = -1;
565 static unsigned char *str;
566 static char outstr[80];
567 char *s;
568 int i, j;
569
570 if (strsize < len) {
571 if (str)
572 free(str);
573 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000574 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 return;
576 }
577 strsize = len;
578 }
579
580 if (umoven(tcp, addr, len, (char *) str) < 0)
581 return;
582
583 for (i = 0; i < len; i += 16) {
584 s = outstr;
585 sprintf(s, " | %05x ", i);
586 s += 9;
587 for (j = 0; j < 16; j++) {
588 if (j == 8)
589 *s++ = ' ';
590 if (i + j < len) {
591 sprintf(s, " %02x", str[i + j]);
592 s += 3;
593 }
594 else {
595 *s++ = ' '; *s++ = ' '; *s++ = ' ';
596 }
597 }
598 *s++ = ' '; *s++ = ' ';
599 for (j = 0; j < 16; j++) {
600 if (j == 8)
601 *s++ = ' ';
602 if (i + j < len) {
603 if (isprint(str[i + j]))
604 *s++ = str[i + j];
605 else
606 *s++ = '.';
607 }
608 else
609 *s++ = ' ';
610 }
611 tprintf("%s |\n", outstr);
612 }
613}
614
615#define PAGMASK (~(PAGSIZ - 1))
616/*
617 * move `len' bytes of data from process `pid'
618 * at address `addr' to our space at `laddr'
619 */
620int
621umoven(tcp, addr, len, laddr)
622struct tcb *tcp;
623long addr;
624int len;
625char *laddr;
626{
627
628#ifdef LINUX
629 int pid = tcp->pid;
630 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000631 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000632 union {
633 long val;
634 char x[sizeof(long)];
635 } u;
636
637 if (addr & (sizeof(long) - 1)) {
638 /* addr not a multiple of sizeof(long) */
639 n = addr - (addr & -sizeof(long)); /* residue */
640 addr &= -sizeof(long); /* residue */
641 errno = 0;
642 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
643 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000644 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000645 /* Ran into 'end of memory' - stupid "printpath" */
646 return 0;
647 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000648 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000649 perror("ptrace: umoven");
650 return -1;
651 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000652 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000653 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
654 addr += sizeof(long), laddr += m, len -= m;
655 }
656 while (len) {
657 errno = 0;
658 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
659 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000660 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000661 /* Ran into 'end of memory' - stupid "printpath" */
662 return 0;
663 }
Roland McGrath4db26242003-01-30 20:15:19 +0000664 if (addr != 0)
665 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000666 return -1;
667 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000668 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000669 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
670 addr += sizeof(long), laddr += m, len -= m;
671 }
672#endif /* LINUX */
673
674#ifdef SUNOS4
675 int pid = tcp->pid;
676#if 0
677 int n, m;
678 union {
679 long val;
680 char x[sizeof(long)];
681 } u;
682
683 if (addr & (sizeof(long) - 1)) {
684 /* addr not a multiple of sizeof(long) */
685 n = addr - (addr & -sizeof(long)); /* residue */
686 addr &= -sizeof(long); /* residue */
687 errno = 0;
688 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
689 if (errno) {
690 perror("umoven");
691 return -1;
692 }
693 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
694 addr += sizeof(long), laddr += m, len -= m;
695 }
696 while (len) {
697 errno = 0;
698 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
699 if (errno) {
700 perror("umoven");
701 return -1;
702 }
703 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
704 addr += sizeof(long), laddr += m, len -= m;
705 }
706#else /* !oldway */
707 int n;
708
709 while (len) {
710 n = MIN(len, PAGSIZ);
711 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
712 if (ptrace(PTRACE_READDATA, pid,
713 (char *) addr, len, laddr) < 0) {
714 perror("umoven: ptrace(PTRACE_READDATA, ...)");
715 abort();
716 return -1;
717 }
718 len -= n;
719 addr += n;
720 laddr += n;
721 }
722#endif /* !oldway */
723#endif /* SUNOS4 */
724
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000725#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000726#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000727 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000728#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000729 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000730#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000731 lseek(fd, addr, SEEK_SET);
732 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000733 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000734#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735
736 return 0;
737}
738
739/*
740 * like `umove' but make the additional effort of looking
741 * for a terminating zero byte.
742 */
743int
744umovestr(tcp, addr, len, laddr)
745struct tcb *tcp;
746long addr;
747int len;
748char *laddr;
749{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000750#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000751#ifdef HAVE_MP_PROCFS
752 int fd = tcp->pfd_as;
753#else
754 int fd = tcp->pfd;
755#endif
756 /* Some systems (e.g. FreeBSD) can be upset if we read off the
757 end of valid memory, avoid this by trying to read up
758 to page boundaries. But we don't know what a page is (and
759 getpagesize(2) (if it exists) doesn't necessarily return
760 hardware page size). Assume all pages >= 1024 (a-historical
761 I know) */
762
763 int page = 1024; /* How to find this? */
764 int move = page - (addr & (page - 1));
765 int left = len;
766
767 lseek(fd, addr, SEEK_SET);
768
769 while (left) {
770 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000771 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000772 return left != len ? 0 : -1;
773 if (memchr (laddr, 0, move)) break;
774 left -= move;
775 laddr += move;
776 addr += move;
777 move = page;
778 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000779#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000780 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000781 int pid = tcp->pid;
782 int i, n, m;
783 union {
784 long val;
785 char x[sizeof(long)];
786 } u;
787
788 if (addr & (sizeof(long) - 1)) {
789 /* addr not a multiple of sizeof(long) */
790 n = addr - (addr & -sizeof(long)); /* residue */
791 addr &= -sizeof(long); /* residue */
792 errno = 0;
793 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
794 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000795 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796 /* Ran into 'end of memory' - stupid "printpath" */
797 return 0;
798 }
799 perror("umovestr");
800 return -1;
801 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000802 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
804 while (n & (sizeof(long) - 1))
805 if (u.x[n++] == '\0')
806 return 0;
807 addr += sizeof(long), laddr += m, len -= m;
808 }
809 while (len) {
810 errno = 0;
811 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
812 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000813 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000814 /* Ran into 'end of memory' - stupid "printpath" */
815 return 0;
816 }
817 perror("umovestr");
818 return -1;
819 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000820 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000821 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
822 for (i = 0; i < sizeof(long); i++)
823 if (u.x[i] == '\0')
824 return 0;
825
826 addr += sizeof(long), laddr += m, len -= m;
827 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000828#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000829 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830}
831
832#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000833#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000834#define PTRACE_WRITETEXT 101
835#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000836#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000837#endif /* LINUX */
838
839#ifdef SUNOS4
840
841static int
842uload(cmd, pid, addr, len, laddr)
843int cmd;
844int pid;
845long addr;
846int len;
847char *laddr;
848{
849#if 0
850 int n;
851
852 while (len) {
853 n = MIN(len, PAGSIZ);
854 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
855 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
856 perror("uload: ptrace(PTRACE_WRITE, ...)");
857 return -1;
858 }
859 len -= n;
860 addr += n;
861 laddr += n;
862 }
863#else
864 int peek, poke;
865 int n, m;
866 union {
867 long val;
868 char x[sizeof(long)];
869 } u;
870
871 if (cmd == PTRACE_WRITETEXT) {
872 peek = PTRACE_PEEKTEXT;
873 poke = PTRACE_POKETEXT;
874 }
875 else {
876 peek = PTRACE_PEEKDATA;
877 poke = PTRACE_POKEDATA;
878 }
879 if (addr & (sizeof(long) - 1)) {
880 /* addr not a multiple of sizeof(long) */
881 n = addr - (addr & -sizeof(long)); /* residue */
882 addr &= -sizeof(long);
883 errno = 0;
884 u.val = ptrace(peek, pid, (char *) addr, 0);
885 if (errno) {
886 perror("uload: POKE");
887 return -1;
888 }
889 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
890 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
891 perror("uload: POKE");
892 return -1;
893 }
894 addr += sizeof(long), laddr += m, len -= m;
895 }
896 while (len) {
897 if (len < sizeof(long))
898 u.val = ptrace(peek, pid, (char *) addr, 0);
899 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
900 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
901 perror("uload: POKE");
902 return -1;
903 }
904 addr += sizeof(long), laddr += m, len -= m;
905 }
906#endif
907 return 0;
908}
909
910int
911tload(pid, addr, len, laddr)
912int pid;
913int addr, len;
914char *laddr;
915{
916 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
917}
918
919int
920dload(pid, addr, len, laddr)
921int pid;
922int addr;
923int len;
924char *laddr;
925{
926 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
927}
928
929#endif /* SUNOS4 */
930
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000931#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000932
933int
934upeek(pid, off, res)
935int pid;
936long off;
937long *res;
938{
939 long val;
940
941#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
942 {
943 static int is_sun4m = -1;
944 struct utsname name;
945
946 /* Round up the usual suspects. */
947 if (is_sun4m == -1) {
948 if (uname(&name) < 0) {
949 perror("upeek: uname?");
950 exit(1);
951 }
952 is_sun4m = strcmp(name.machine, "sun4m") == 0;
953 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000954 extern const struct xlat struct_user_offsets[];
955 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000956
957 for (x = struct_user_offsets; x->str; x++)
958 x->val += 1024;
959 }
960 }
961 if (is_sun4m)
962 off += 1024;
963 }
964#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
965 errno = 0;
966 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
967 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000968 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000969 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000970 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 return -1;
972 }
973 *res = val;
974 return 0;
975}
976
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000977#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978
979long
980getpc(tcp)
981struct tcb *tcp;
982{
983
984#ifdef LINUX
985 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000986#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
988 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000989#elif defined(X86_64)
990 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
991 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000992#elif defined(IA64)
993 if (upeek(tcp->pid, PT_B0, &pc) < 0)
994 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000995#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 if (upeek(tcp->pid, 4*15, &pc) < 0)
997 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000998#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000999 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001001#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1003 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001004#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1006 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001007#elif defined(MIPS)
1008 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1009 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001010#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001011 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1013 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001014 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001015#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001016 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001017 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001018#elif defined(HPPA)
1019 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1020 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001021#elif defined(SH)
1022 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1023 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001024#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001025 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1026 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001027#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001028 return pc;
1029#endif /* LINUX */
1030
1031#ifdef SUNOS4
1032 /*
1033 * Return current program counter for `pid'
1034 * Assumes PC is never 0xffffffff
1035 */
1036 struct regs regs;
1037
1038 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1039 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1040 return -1;
1041 }
1042 return regs.r_pc;
1043#endif /* SUNOS4 */
1044
1045#ifdef SVR4
1046 /* XXX */
1047 return 0;
1048#endif /* SVR4 */
1049
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001050#ifdef FREEBSD
1051 struct reg regs;
1052 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1053 return regs.r_eip;
1054#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055}
1056
1057void
1058printcall(tcp)
1059struct tcb *tcp;
1060{
Roland McGrath7a918832005-02-02 20:55:23 +00001061#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1062 sizeof(long) == 8 ? "[????????????????] " : \
1063 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064
1065#ifdef LINUX
1066#ifdef I386
1067 long eip;
1068
1069 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001070 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001071 return;
1072 }
1073 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001074
1075#elif defined(S390) || defined(S390X)
1076 long psw;
1077 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001078 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001079 return;
1080 }
1081#ifdef S390
1082 tprintf("[%08lx] ", psw);
1083#elif S390X
1084 tprintf("[%16lx] ", psw);
1085#endif
1086
Michal Ludvig0e035502002-09-23 15:41:01 +00001087#elif defined(X86_64)
1088 long rip;
1089
1090 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001091 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001092 return;
1093 }
1094 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001095#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001096 long ip;
1097
1098 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001099 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001100 return;
1101 }
1102 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001103#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001104 long pc;
1105
Roland McGratheb285352003-01-14 09:59:00 +00001106 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 tprintf ("[????????] ");
1108 return;
1109 }
1110 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001111#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112 long pc;
1113
1114 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1115 tprintf ("[????????] ");
1116 return;
1117 }
1118 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001119#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 long pc;
1121
1122 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001123 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 return;
1125 }
1126 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001127#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001128 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001129 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001130 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 return;
1132 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001133 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001134#elif defined(HPPA)
1135 long pc;
1136
1137 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1138 tprintf ("[????????] ");
1139 return;
1140 }
1141 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001142#elif defined(MIPS)
1143 long pc;
1144
1145 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1146 tprintf ("[????????] ");
1147 return;
1148 }
1149 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001150#elif defined(SH)
1151 long pc;
1152
1153 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1154 tprintf ("[????????] ");
1155 return;
1156 }
1157 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001158#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001159 long pc;
1160
1161 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001162 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001163 return;
1164 }
1165 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001166#elif defined(ARM)
1167 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001168
Roland McGrathef388682003-06-03 23:28:59 +00001169 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001170 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001171 return;
1172 }
1173 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001174#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175#endif /* LINUX */
1176
1177#ifdef SUNOS4
1178 struct regs regs;
1179
1180 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1181 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001182 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001183 return;
1184 }
1185 tprintf("[%08x] ", regs.r_o7);
1186#endif /* SUNOS4 */
1187
1188#ifdef SVR4
1189 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001190 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191#endif
1192
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001193#ifdef FREEBSD
1194 struct reg regs;
1195 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1196 tprintf("[%08x] ", regs.r_eip);
1197#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001198}
1199
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001200#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202#if defined LINUX
1203
1204#include <sys/syscall.h>
1205#ifndef CLONE_PTRACE
1206# define CLONE_PTRACE 0x00002000
1207#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001208#ifndef CLONE_STOPPED
1209# define CLONE_STOPPED 0x02000000
1210#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001211
1212#ifdef IA64
1213
Roland McGrath08267b82004-02-20 22:56:43 +00001214/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1215 subsystem has them for x86... */
1216#define SYS_fork 2
1217#define SYS_vfork 190
1218
Roland McGrathd81f1d92003-01-09 06:53:34 +00001219typedef unsigned long *arg_setup_state;
1220
1221static int
1222arg_setup(struct tcb *tcp, arg_setup_state *state)
1223{
1224 unsigned long *bsp, cfm, sof, sol;
1225
Roland McGrath08267b82004-02-20 22:56:43 +00001226 if (ia32)
1227 return 0;
1228
Roland McGrathd81f1d92003-01-09 06:53:34 +00001229 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1230 return -1;
1231 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1232 return -1;
1233
1234 sof = (cfm >> 0) & 0x7f;
1235 sol = (cfm >> 7) & 0x7f;
1236 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1237
1238 *state = bsp;
1239 return 0;
1240}
1241
1242# define arg_finish_change(tcp, state) 0
1243
1244#ifdef SYS_fork
1245static int
1246get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1247{
Roland McGrath08267b82004-02-20 22:56:43 +00001248 int ret;
1249
1250 if (ia32)
1251 ret = upeek (tcp->pid, PT_R11, valp);
1252 else
1253 ret = umoven (tcp,
1254 (unsigned long) ia64_rse_skip_regs(*state, 0),
1255 sizeof(long), (void *) valp);
1256 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001257}
1258
1259static int
1260get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1261{
Roland McGrath08267b82004-02-20 22:56:43 +00001262 int ret;
1263
1264 if (ia32)
1265 ret = upeek (tcp->pid, PT_R9, valp);
1266 else
1267 ret = umoven (tcp,
1268 (unsigned long) ia64_rse_skip_regs(*state, 1),
1269 sizeof(long), (void *) valp);
1270 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001271}
1272#endif
1273
1274static int
1275set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1276{
Roland McGrath08267b82004-02-20 22:56:43 +00001277 int req = PTRACE_POKEDATA;
1278 void *ap;
1279
1280 if (ia32) {
1281 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1282 req = PTRACE_POKEUSER;
1283 } else
1284 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001285 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001286 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001287 return errno ? -1 : 0;
1288}
1289
1290static int
1291set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1292{
Roland McGrath08267b82004-02-20 22:56:43 +00001293 int req = PTRACE_POKEDATA;
1294 void *ap;
1295
1296 if (ia32) {
1297 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1298 req = PTRACE_POKEUSER;
1299 } else
1300 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001301 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001302 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001303 return errno ? -1 : 0;
1304}
1305
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001306#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001307
1308typedef struct regs arg_setup_state;
1309
1310# define arg_setup(tcp, state) \
1311 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1312# define arg_finish_change(tcp, state) \
1313 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1314
1315# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1316# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1317# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1318# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001319# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001320
1321#else
1322
1323# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001324/* Note: this is only true for the `clone' system call, which handles
1325 arguments specially. We could as well say that its first two arguments
1326 are swapped relative to other architectures, but that would just be
1327 another #ifdef in the calls. */
1328# define arg0_offset PT_GPR3
1329# define arg1_offset PT_ORIGGPR2
1330# define restore_arg0(tcp, state, val) ((void) (state), 0)
1331# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001332# define arg0_index 1
1333# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001334# elif defined (ALPHA) || defined (MIPS)
1335# define arg0_offset REG_A0
1336# define arg1_offset (REG_A0+1)
1337# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001338# define arg0_offset (sizeof(unsigned long)*PT_R3)
1339# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001340# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001341# elif defined (HPPA)
1342# define arg0_offset PT_GR26
1343# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001344# elif defined (X86_64)
1345# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1346# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001347# elif defined (SH)
1348# define arg0_offset (4*(REG_REG0+4))
1349# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001350# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001351 /* ABI defines arg0 & 1 in r2 & r3 */
1352# define arg0_offset (REG_OFFSET+16)
1353# define arg1_offset (REG_OFFSET+24)
1354# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001355# else
1356# define arg0_offset 0
1357# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001358# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001359# define restore_arg0(tcp, state, val) 0
1360# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001361# endif
1362
1363typedef int arg_setup_state;
1364
1365# define arg_setup(tcp, state) (0)
1366# define arg_finish_change(tcp, state) 0
1367# define get_arg0(tcp, cookie, valp) \
1368 (upeek ((tcp)->pid, arg0_offset, (valp)))
1369# define get_arg1(tcp, cookie, valp) \
1370 (upeek ((tcp)->pid, arg1_offset, (valp)))
1371
1372static int
1373set_arg0 (struct tcb *tcp, void *cookie, long val)
1374{
Roland McGrath76989d72005-06-07 23:21:31 +00001375 long oldval,newval;
1376 if (get_arg0(tcp, cookie, &oldval) < 0)
1377 abort ();
1378 if (ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val) < 0)
1379 return -1;
1380 if (get_arg0(tcp, cookie, &newval) < 0)
1381 abort ();
1382 fprintf(stderr, "XXX old %lx set %lx new %lx\n",
1383 oldval,val,newval);
1384 return 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001385}
1386
1387static int
1388set_arg1 (struct tcb *tcp, void *cookie, long val)
1389{
1390 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1391}
1392
1393#endif
1394
Roland McGrathe1df47f2003-01-14 09:46:15 +00001395#ifndef restore_arg0
1396# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1397#endif
1398#ifndef restore_arg1
1399# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1400#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401
Roland McGrath90d0afd2004-03-01 21:05:16 +00001402#ifndef arg0_index
1403# define arg0_index 0
1404# define arg1_index 1
1405#endif
1406
Roland McGrathd81f1d92003-01-09 06:53:34 +00001407int
1408setbpt(tcp)
1409struct tcb *tcp;
1410{
1411 extern int change_syscall(struct tcb *, int);
1412 arg_setup_state state;
1413
1414 if (tcp->flags & TCB_BPTSET) {
1415 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1416 return -1;
1417 }
1418
Roland McGrath76989d72005-06-07 23:21:31 +00001419 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001420#ifdef SYS_vfork
1421 case SYS_vfork:
1422#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001423#ifdef SYS_fork
1424 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001425#endif
1426#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001427 if (arg_setup (tcp, &state) < 0
1428 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1429 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1430 || change_syscall(tcp, SYS_clone) < 0
1431 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1432 || set_arg1 (tcp, &state, 0) < 0
1433 || arg_finish_change (tcp, &state) < 0)
1434 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001435 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1436 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437 tcp->flags |= TCB_BPTSET;
1438 return 0;
1439#endif
1440
1441 case SYS_clone:
1442#ifdef SYS_clone2
1443 case SYS_clone2:
1444#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001445 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001446 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001447 || set_arg0 (tcp, &state,
1448 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001449 || arg_finish_change (tcp, &state) < 0))
1450 return -1;
1451 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001452 tcp->inst[0] = tcp->u_arg[arg0_index];
1453 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001454 return 0;
1455
1456 default:
1457 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1458 tcp->scno, tcp->pid);
1459 break;
1460 }
1461
1462 return -1;
1463}
1464
1465int
1466clearbpt(tcp)
1467struct tcb *tcp;
1468{
1469 arg_setup_state state;
1470 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001471 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1472 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001473 || arg_finish_change (tcp, &state))
1474 return -1;
1475 tcp->flags &= ~TCB_BPTSET;
1476 return 0;
1477}
1478
1479#else
1480
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481int
1482setbpt(tcp)
1483struct tcb *tcp;
1484{
1485
1486#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001487#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001488 /* We simply use the SunOS breakpoint code. */
1489
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001490 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001491 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492#define LOOPA 0x30800000 /* ba,a 0 */
1493
1494 if (tcp->flags & TCB_BPTSET) {
1495 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1496 return -1;
1497 }
1498 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1499 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1500 return -1;
1501 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001502 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 errno = 0;
1504 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1505 if(errno) {
1506 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1507 return -1;
1508 }
1509
1510 /*
1511 * XXX - BRUTAL MODE ON
1512 * We cannot set a real BPT in the child, since it will not be
1513 * traced at the moment it will reach the trap and would probably
1514 * die with a core dump.
1515 * Thus, we are force our way in by taking out two instructions
1516 * and insert an eternal loop instead, in expectance of the SIGSTOP
1517 * generated by out PTRACE_ATTACH.
1518 * Of cause, if we evaporate ourselves in the middle of all this...
1519 */
1520 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001521 inst = LOOPA;
1522#if defined (SPARC64)
1523 inst <<= 32;
1524 inst |= (tcp->inst[0] & 0xffffffffUL);
1525#endif
1526 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527 if(errno) {
1528 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1529 return -1;
1530 }
1531 tcp->flags |= TCB_BPTSET;
1532
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001533#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001534#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001535 if (ia32) {
1536# define LOOP 0x0000feeb
1537 if (tcp->flags & TCB_BPTSET) {
1538 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1539 tcp->pid);
1540 return -1;
1541 }
1542 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1543 return -1;
1544 if (debug)
1545 fprintf(stderr, "[%d] setting bpt at %lx\n",
1546 tcp->pid, tcp->baddr);
1547 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1548 (char *) tcp->baddr, 0);
1549 if (errno) {
1550 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1551 return -1;
1552 }
1553 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1554 if (errno) {
1555 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1556 return -1;
1557 }
1558 tcp->flags |= TCB_BPTSET;
1559 } else {
1560 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001561 * Our strategy here is to replace the bundle that
1562 * contained the clone() syscall with a bundle of the
1563 * form:
1564 *
1565 * { 1: br 1b; br 1b; br 1b }
1566 *
1567 * This ensures that the newly forked child will loop
1568 * endlessly until we've got a chance to attach to it.
1569 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001570# define LOOP0 0x0000100000000017
1571# define LOOP1 0x4000000000200000
1572 unsigned long addr, ipsr;
1573 pid_t pid;
1574
1575 pid = tcp->pid;
1576 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1577 return -1;
1578 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1579 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001580 /* store "ri" in low two bits */
1581 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001582
1583 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001584 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1585 0);
1586 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1587 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001588 if (errno) {
1589 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1590 return -1;
1591 }
1592
1593 errno = 0;
1594 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1595 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1596 if (errno) {
1597 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1598 return -1;
1599 }
1600 tcp->flags |= TCB_BPTSET;
1601 }
1602#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603
Michal Ludvig0e035502002-09-23 15:41:01 +00001604#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001605#define LOOP 0x0000feeb
1606#elif defined (M68K)
1607#define LOOP 0x60fe0000
1608#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001609#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001611#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001613#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001614#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001615#define LOOP 0x1000ffff
1616#elif defined(S390)
1617#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001618#elif defined(S390X)
1619#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001620#elif defined(HPPA)
1621#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001622#elif defined(SH)
1623#ifdef __LITTLE_ENDIAN__
1624#define LOOP 0x0000affe
1625#else
1626#define LOOP 0xfeaf0000
1627#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001628#else
1629#error unknown architecture
1630#endif
1631
1632 if (tcp->flags & TCB_BPTSET) {
1633 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1634 return -1;
1635 }
1636#if defined (I386)
1637 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1638 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001639#elif defined (X86_64)
1640 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1641 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642#elif defined (M68K)
1643 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1644 return -1;
1645#elif defined (ALPHA)
1646 return -1;
1647#elif defined (ARM)
1648 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001649#elif defined (MIPS)
1650 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001651#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001652 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001653 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001654#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001655 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1656 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001657#elif defined(HPPA)
1658 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1659 return -1;
1660 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001661#elif defined(SH)
1662 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1663 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001664#else
1665#error unknown architecture
1666#endif
1667 if (debug)
1668 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1669 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1670 if (errno) {
1671 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1672 return -1;
1673 }
1674 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1675 if (errno) {
1676 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1677 return -1;
1678 }
1679 tcp->flags |= TCB_BPTSET;
1680
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001681#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001682#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683#endif /* LINUX */
1684
1685#ifdef SUNOS4
1686#ifdef SPARC /* This code is slightly sparc specific */
1687
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001688 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689#define BPT 0x91d02001 /* ta 1 */
1690#define LOOP 0x10800000 /* ba 0 */
1691#define LOOPA 0x30800000 /* ba,a 0 */
1692#define NOP 0x01000000
1693#if LOOPA
1694 static int loopdeloop[1] = {LOOPA};
1695#else
1696 static int loopdeloop[2] = {LOOP, NOP};
1697#endif
1698
1699 if (tcp->flags & TCB_BPTSET) {
1700 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1701 return -1;
1702 }
1703 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1704 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1705 return -1;
1706 }
1707 tcp->baddr = regs.r_o7 + 8;
1708 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1709 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1710 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1711 return -1;
1712 }
1713
1714 /*
1715 * XXX - BRUTAL MODE ON
1716 * We cannot set a real BPT in the child, since it will not be
1717 * traced at the moment it will reach the trap and would probably
1718 * die with a core dump.
1719 * Thus, we are force our way in by taking out two instructions
1720 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1721 * generated by out PTRACE_ATTACH.
1722 * Of cause, if we evaporate ourselves in the middle of all this...
1723 */
1724 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1725 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1726 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1727 return -1;
1728 }
1729 tcp->flags |= TCB_BPTSET;
1730
1731#endif /* SPARC */
1732#endif /* SUNOS4 */
1733
1734 return 0;
1735}
1736
1737int
1738clearbpt(tcp)
1739struct tcb *tcp;
1740{
1741
1742#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001743#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001744 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001745#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001747#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001748 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001749#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001751#elif defined(HPPA)
1752 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001753#elif defined(SH)
1754 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001755#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001756
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001757#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758 /* Again, we borrow the SunOS breakpoint code. */
1759 if (!(tcp->flags & TCB_BPTSET)) {
1760 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1761 return -1;
1762 }
1763 errno = 0;
1764 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1765 if(errno) {
1766 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1767 return -1;
1768 }
1769 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001770#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001771 if (ia32) {
1772 unsigned long addr;
1773
1774 if (debug)
1775 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1776 if (!(tcp->flags & TCB_BPTSET)) {
1777 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1778 return -1;
1779 }
1780 errno = 0;
1781 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1782 if (errno) {
1783 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1784 return -1;
1785 }
1786 tcp->flags &= ~TCB_BPTSET;
1787
1788 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1789 return -1;
1790 if (addr != tcp->baddr) {
1791 /* The breakpoint has not been reached yet. */
1792 if (debug)
1793 fprintf(stderr,
1794 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1795 addr, tcp->baddr);
1796 return 0;
1797 }
1798 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001799 unsigned long addr, ipsr;
1800 pid_t pid;
1801
1802 pid = tcp->pid;
1803
1804 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1805 return -1;
1806 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1807 return -1;
1808
1809 /* restore original bundle: */
1810 errno = 0;
1811 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1812 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1813 if (errno) {
1814 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1815 return -1;
1816 }
1817
1818 /* restore original "ri" in ipsr: */
1819 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1820 errno = 0;
1821 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1822 if (errno) {
1823 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1824 return -1;
1825 }
1826
1827 tcp->flags &= ~TCB_BPTSET;
1828
1829 if (addr != (tcp->baddr & ~0x3)) {
1830 /* the breakpoint has not been reached yet. */
1831 if (debug)
1832 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1833 addr, tcp->baddr);
1834 return 0;
1835 }
1836 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001837#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001838
1839 if (debug)
1840 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1841 if (!(tcp->flags & TCB_BPTSET)) {
1842 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1843 return -1;
1844 }
1845 errno = 0;
1846 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1847 if (errno) {
1848 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1849 return -1;
1850 }
1851 tcp->flags &= ~TCB_BPTSET;
1852
1853#ifdef I386
1854 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1855 return -1;
1856 if (eip != tcp->baddr) {
1857 /* The breakpoint has not been reached yet. */
1858 if (debug)
1859 fprintf(stderr,
1860 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1861 eip, tcp->baddr);
1862 return 0;
1863 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001864#elif defined(X86_64)
1865 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1866 return -1;
1867 if (eip != tcp->baddr) {
1868 /* The breakpoint has not been reached yet. */
1869 if (debug)
1870 fprintf(stderr,
1871 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1872 eip, tcp->baddr);
1873 return 0;
1874 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001875#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001876 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001877 return -1;
1878 if (pc != tcp->baddr) {
1879 /* The breakpoint has not been reached yet. */
1880 if (debug)
1881 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1882 pc, tcp->baddr);
1883 return 0;
1884 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001885#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001886 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1887 return -1;
1888 if (pc != tcp->baddr) {
1889 /* The breakpoint has not been reached yet. */
1890 if (debug)
1891 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1892 pc, tcp->baddr);
1893 return 0;
1894 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001895#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001896 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1897 return -1;
1898 if (pc != tcp->baddr) {
1899 /* The breakpoint has not been reached yet. */
1900 if (debug)
1901 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1902 pc, tcp->baddr);
1903 return 0;
1904 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001905#elif defined(HPPA)
1906 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1907 return -1;
1908 iaoq &= ~0x03;
1909 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1910 /* The breakpoint has not been reached yet. */
1911 if (debug)
1912 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1913 iaoq, tcp->baddr);
1914 return 0;
1915 }
1916 iaoq = tcp->baddr | 3;
1917 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1918 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1919 * has no significant effect.
1920 */
1921 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1922 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001923#elif defined(SH)
1924 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1925 return -1;
1926 if (pc != tcp->baddr) {
1927 /* The breakpoint has not been reached yet. */
1928 if (debug)
1929 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1930 pc, tcp->baddr);
1931 return 0;
1932 }
1933
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001934#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001935#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936#endif /* LINUX */
1937
1938#ifdef SUNOS4
1939#ifdef SPARC
1940
1941#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001942 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001943#endif
1944
1945 if (!(tcp->flags & TCB_BPTSET)) {
1946 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1947 return -1;
1948 }
1949 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1950 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1951 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1952 return -1;
1953 }
1954 tcp->flags &= ~TCB_BPTSET;
1955
1956#if !LOOPA
1957 /*
1958 * Since we don't have a single instruction breakpoint, we may have
1959 * to adjust the program counter after removing the our `breakpoint'.
1960 */
1961 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1962 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1963 return -1;
1964 }
1965 if ((regs.r_pc < tcp->baddr) ||
1966 (regs.r_pc > tcp->baddr + 4)) {
1967 /* The breakpoint has not been reached yet */
1968 if (debug)
1969 fprintf(stderr,
1970 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1971 regs.r_pc, tcp->parent->baddr);
1972 return 0;
1973 }
1974 if (regs.r_pc != tcp->baddr)
1975 if (debug)
1976 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1977 regs.r_pc, tcp->baddr);
1978
1979 regs.r_pc = tcp->baddr;
1980 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1981 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1982 return -1;
1983 }
1984#endif /* LOOPA */
1985#endif /* SPARC */
1986#endif /* SUNOS4 */
1987
1988 return 0;
1989}
1990
Roland McGrathd81f1d92003-01-09 06:53:34 +00001991#endif
1992
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001993#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001994
1995#ifdef SUNOS4
1996
1997static int
1998getex(pid, hdr)
1999int pid;
2000struct exec *hdr;
2001{
2002 int n;
2003
2004 for (n = 0; n < sizeof *hdr; n += 4) {
2005 long res;
2006 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2007 return -1;
2008 memcpy(((char *) hdr) + n, &res, 4);
2009 }
2010 if (debug) {
2011 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2012 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2013 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2014 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2015 }
2016 return 0;
2017}
2018
2019int
2020fixvfork(tcp)
2021struct tcb *tcp;
2022{
2023 int pid = tcp->pid;
2024 /*
2025 * Change `vfork' in a freshly exec'ed dynamically linked
2026 * executable's (internal) symbol table to plain old `fork'
2027 */
2028
2029 struct exec hdr;
2030 struct link_dynamic dyn;
2031 struct link_dynamic_2 ld;
2032 char *strtab, *cp;
2033
2034 if (getex(pid, &hdr) < 0)
2035 return -1;
2036 if (!hdr.a_dynamic)
2037 return -1;
2038
2039 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2040 fprintf(stderr, "Cannot read DYNAMIC\n");
2041 return -1;
2042 }
2043 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2044 fprintf(stderr, "Cannot read link_dynamic_2\n");
2045 return -1;
2046 }
2047 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002048 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049 return -1;
2050 }
2051 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2052 (int)ld.ld_symb_size, strtab) < 0)
2053 goto err;
2054
2055#if 0
2056 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2057 fprintf(stderr, "[symbol: %s]\n", cp);
2058 cp += strlen(cp)+1;
2059 }
2060 return 0;
2061#endif
2062 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2063 if (strcmp(cp, "_vfork") == 0) {
2064 if (debug)
2065 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2066 strcpy(cp, "_fork");
2067 break;
2068 }
2069 cp += strlen(cp)+1;
2070 }
2071 if (cp < strtab + ld.ld_symb_size)
2072 /*
2073 * Write entire symbol table back to avoid
2074 * memory alignment bugs in ptrace
2075 */
2076 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2077 (int)ld.ld_symb_size, strtab) < 0)
2078 goto err;
2079
2080 free(strtab);
2081 return 0;
2082
2083err:
2084 free(strtab);
2085 return -1;
2086}
2087
2088#endif /* SUNOS4 */