blob: 3c070750abc0ddbfbff6909f15d7b565de281812 [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 McGrathca85b972005-06-07 23:22:08 +00001375 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001376}
1377
1378static int
1379set_arg1 (struct tcb *tcp, void *cookie, long val)
1380{
1381 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1382}
1383
1384#endif
1385
Roland McGrathe1df47f2003-01-14 09:46:15 +00001386#ifndef restore_arg0
1387# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1388#endif
1389#ifndef restore_arg1
1390# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1391#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001392
Roland McGrath90d0afd2004-03-01 21:05:16 +00001393#ifndef arg0_index
1394# define arg0_index 0
1395# define arg1_index 1
1396#endif
1397
Roland McGrathd81f1d92003-01-09 06:53:34 +00001398int
1399setbpt(tcp)
1400struct tcb *tcp;
1401{
1402 extern int change_syscall(struct tcb *, int);
1403 arg_setup_state state;
1404
1405 if (tcp->flags & TCB_BPTSET) {
1406 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1407 return -1;
1408 }
1409
Roland McGrath76989d72005-06-07 23:21:31 +00001410 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001411#ifdef SYS_vfork
1412 case SYS_vfork:
1413#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001414#ifdef SYS_fork
1415 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001416#endif
1417#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001418 if (arg_setup (tcp, &state) < 0
1419 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1420 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1421 || change_syscall(tcp, SYS_clone) < 0
1422 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1423 || set_arg1 (tcp, &state, 0) < 0
1424 || arg_finish_change (tcp, &state) < 0)
1425 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001426 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1427 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001428 tcp->flags |= TCB_BPTSET;
1429 return 0;
1430#endif
1431
1432 case SYS_clone:
1433#ifdef SYS_clone2
1434 case SYS_clone2:
1435#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001436 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001437 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001438 || set_arg0 (tcp, &state,
1439 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001440 || arg_finish_change (tcp, &state) < 0))
1441 return -1;
1442 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001443 tcp->inst[0] = tcp->u_arg[arg0_index];
1444 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001445 return 0;
1446
1447 default:
1448 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1449 tcp->scno, tcp->pid);
1450 break;
1451 }
1452
1453 return -1;
1454}
1455
1456int
1457clearbpt(tcp)
1458struct tcb *tcp;
1459{
1460 arg_setup_state state;
1461 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001462 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1463 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001464 || arg_finish_change (tcp, &state))
1465 return -1;
1466 tcp->flags &= ~TCB_BPTSET;
1467 return 0;
1468}
1469
1470#else
1471
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001472int
1473setbpt(tcp)
1474struct tcb *tcp;
1475{
1476
1477#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001478#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479 /* We simply use the SunOS breakpoint code. */
1480
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001481 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001482 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483#define LOOPA 0x30800000 /* ba,a 0 */
1484
1485 if (tcp->flags & TCB_BPTSET) {
1486 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1487 return -1;
1488 }
1489 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1490 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1491 return -1;
1492 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001493 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 errno = 0;
1495 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1496 if(errno) {
1497 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1498 return -1;
1499 }
1500
1501 /*
1502 * XXX - BRUTAL MODE ON
1503 * We cannot set a real BPT in the child, since it will not be
1504 * traced at the moment it will reach the trap and would probably
1505 * die with a core dump.
1506 * Thus, we are force our way in by taking out two instructions
1507 * and insert an eternal loop instead, in expectance of the SIGSTOP
1508 * generated by out PTRACE_ATTACH.
1509 * Of cause, if we evaporate ourselves in the middle of all this...
1510 */
1511 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001512 inst = LOOPA;
1513#if defined (SPARC64)
1514 inst <<= 32;
1515 inst |= (tcp->inst[0] & 0xffffffffUL);
1516#endif
1517 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518 if(errno) {
1519 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1520 return -1;
1521 }
1522 tcp->flags |= TCB_BPTSET;
1523
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001524#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001525#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001526 if (ia32) {
1527# define LOOP 0x0000feeb
1528 if (tcp->flags & TCB_BPTSET) {
1529 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1530 tcp->pid);
1531 return -1;
1532 }
1533 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1534 return -1;
1535 if (debug)
1536 fprintf(stderr, "[%d] setting bpt at %lx\n",
1537 tcp->pid, tcp->baddr);
1538 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1539 (char *) tcp->baddr, 0);
1540 if (errno) {
1541 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1542 return -1;
1543 }
1544 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1545 if (errno) {
1546 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1547 return -1;
1548 }
1549 tcp->flags |= TCB_BPTSET;
1550 } else {
1551 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001552 * Our strategy here is to replace the bundle that
1553 * contained the clone() syscall with a bundle of the
1554 * form:
1555 *
1556 * { 1: br 1b; br 1b; br 1b }
1557 *
1558 * This ensures that the newly forked child will loop
1559 * endlessly until we've got a chance to attach to it.
1560 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001561# define LOOP0 0x0000100000000017
1562# define LOOP1 0x4000000000200000
1563 unsigned long addr, ipsr;
1564 pid_t pid;
1565
1566 pid = tcp->pid;
1567 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1568 return -1;
1569 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1570 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001571 /* store "ri" in low two bits */
1572 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001573
1574 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001575 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1576 0);
1577 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1578 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001579 if (errno) {
1580 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1581 return -1;
1582 }
1583
1584 errno = 0;
1585 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1586 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1587 if (errno) {
1588 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1589 return -1;
1590 }
1591 tcp->flags |= TCB_BPTSET;
1592 }
1593#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594
Michal Ludvig0e035502002-09-23 15:41:01 +00001595#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596#define LOOP 0x0000feeb
1597#elif defined (M68K)
1598#define LOOP 0x60fe0000
1599#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001600#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001602#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001604#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001605#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001606#define LOOP 0x1000ffff
1607#elif defined(S390)
1608#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001609#elif defined(S390X)
1610#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001611#elif defined(HPPA)
1612#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001613#elif defined(SH)
1614#ifdef __LITTLE_ENDIAN__
1615#define LOOP 0x0000affe
1616#else
1617#define LOOP 0xfeaf0000
1618#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619#else
1620#error unknown architecture
1621#endif
1622
1623 if (tcp->flags & TCB_BPTSET) {
1624 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1625 return -1;
1626 }
1627#if defined (I386)
1628 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1629 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001630#elif defined (X86_64)
1631 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1632 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633#elif defined (M68K)
1634 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1635 return -1;
1636#elif defined (ALPHA)
1637 return -1;
1638#elif defined (ARM)
1639 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001640#elif defined (MIPS)
1641 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001643 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001645#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001646 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1647 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001648#elif defined(HPPA)
1649 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1650 return -1;
1651 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001652#elif defined(SH)
1653 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1654 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655#else
1656#error unknown architecture
1657#endif
1658 if (debug)
1659 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1660 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1661 if (errno) {
1662 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1663 return -1;
1664 }
1665 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1666 if (errno) {
1667 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1668 return -1;
1669 }
1670 tcp->flags |= TCB_BPTSET;
1671
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001672#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001673#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674#endif /* LINUX */
1675
1676#ifdef SUNOS4
1677#ifdef SPARC /* This code is slightly sparc specific */
1678
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001679 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680#define BPT 0x91d02001 /* ta 1 */
1681#define LOOP 0x10800000 /* ba 0 */
1682#define LOOPA 0x30800000 /* ba,a 0 */
1683#define NOP 0x01000000
1684#if LOOPA
1685 static int loopdeloop[1] = {LOOPA};
1686#else
1687 static int loopdeloop[2] = {LOOP, NOP};
1688#endif
1689
1690 if (tcp->flags & TCB_BPTSET) {
1691 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1692 return -1;
1693 }
1694 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1695 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1696 return -1;
1697 }
1698 tcp->baddr = regs.r_o7 + 8;
1699 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1700 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1701 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1702 return -1;
1703 }
1704
1705 /*
1706 * XXX - BRUTAL MODE ON
1707 * We cannot set a real BPT in the child, since it will not be
1708 * traced at the moment it will reach the trap and would probably
1709 * die with a core dump.
1710 * Thus, we are force our way in by taking out two instructions
1711 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1712 * generated by out PTRACE_ATTACH.
1713 * Of cause, if we evaporate ourselves in the middle of all this...
1714 */
1715 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1716 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1717 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1718 return -1;
1719 }
1720 tcp->flags |= TCB_BPTSET;
1721
1722#endif /* SPARC */
1723#endif /* SUNOS4 */
1724
1725 return 0;
1726}
1727
1728int
1729clearbpt(tcp)
1730struct tcb *tcp;
1731{
1732
1733#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001734#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001736#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001737 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001738#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001740#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001741 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001742#elif defined(HPPA)
1743 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001744#elif defined(SH)
1745 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001746#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001747
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001748#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749 /* Again, we borrow the SunOS breakpoint code. */
1750 if (!(tcp->flags & TCB_BPTSET)) {
1751 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1752 return -1;
1753 }
1754 errno = 0;
1755 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1756 if(errno) {
1757 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1758 return -1;
1759 }
1760 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001761#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001762 if (ia32) {
1763 unsigned long addr;
1764
1765 if (debug)
1766 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1767 if (!(tcp->flags & TCB_BPTSET)) {
1768 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1769 return -1;
1770 }
1771 errno = 0;
1772 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1773 if (errno) {
1774 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1775 return -1;
1776 }
1777 tcp->flags &= ~TCB_BPTSET;
1778
1779 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1780 return -1;
1781 if (addr != tcp->baddr) {
1782 /* The breakpoint has not been reached yet. */
1783 if (debug)
1784 fprintf(stderr,
1785 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1786 addr, tcp->baddr);
1787 return 0;
1788 }
1789 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001790 unsigned long addr, ipsr;
1791 pid_t pid;
1792
1793 pid = tcp->pid;
1794
1795 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1796 return -1;
1797 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1798 return -1;
1799
1800 /* restore original bundle: */
1801 errno = 0;
1802 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1803 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1804 if (errno) {
1805 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1806 return -1;
1807 }
1808
1809 /* restore original "ri" in ipsr: */
1810 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1811 errno = 0;
1812 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1813 if (errno) {
1814 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1815 return -1;
1816 }
1817
1818 tcp->flags &= ~TCB_BPTSET;
1819
1820 if (addr != (tcp->baddr & ~0x3)) {
1821 /* the breakpoint has not been reached yet. */
1822 if (debug)
1823 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1824 addr, tcp->baddr);
1825 return 0;
1826 }
1827 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001828#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829
1830 if (debug)
1831 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1832 if (!(tcp->flags & TCB_BPTSET)) {
1833 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1834 return -1;
1835 }
1836 errno = 0;
1837 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1838 if (errno) {
1839 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1840 return -1;
1841 }
1842 tcp->flags &= ~TCB_BPTSET;
1843
1844#ifdef I386
1845 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1846 return -1;
1847 if (eip != tcp->baddr) {
1848 /* The breakpoint has not been reached yet. */
1849 if (debug)
1850 fprintf(stderr,
1851 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1852 eip, tcp->baddr);
1853 return 0;
1854 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001855#elif defined(X86_64)
1856 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1857 return -1;
1858 if (eip != tcp->baddr) {
1859 /* The breakpoint has not been reached yet. */
1860 if (debug)
1861 fprintf(stderr,
1862 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1863 eip, tcp->baddr);
1864 return 0;
1865 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001866#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001867 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001868 return -1;
1869 if (pc != tcp->baddr) {
1870 /* The breakpoint has not been reached yet. */
1871 if (debug)
1872 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1873 pc, tcp->baddr);
1874 return 0;
1875 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001876#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001877 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1878 return -1;
1879 if (pc != tcp->baddr) {
1880 /* The breakpoint has not been reached yet. */
1881 if (debug)
1882 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1883 pc, tcp->baddr);
1884 return 0;
1885 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001886#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001887 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1888 return -1;
1889 if (pc != tcp->baddr) {
1890 /* The breakpoint has not been reached yet. */
1891 if (debug)
1892 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1893 pc, tcp->baddr);
1894 return 0;
1895 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001896#elif defined(HPPA)
1897 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1898 return -1;
1899 iaoq &= ~0x03;
1900 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1901 /* The breakpoint has not been reached yet. */
1902 if (debug)
1903 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1904 iaoq, tcp->baddr);
1905 return 0;
1906 }
1907 iaoq = tcp->baddr | 3;
1908 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1909 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1910 * has no significant effect.
1911 */
1912 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1913 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001914#elif defined(SH)
1915 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1916 return -1;
1917 if (pc != tcp->baddr) {
1918 /* The breakpoint has not been reached yet. */
1919 if (debug)
1920 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1921 pc, tcp->baddr);
1922 return 0;
1923 }
1924
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001925#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001926#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001927#endif /* LINUX */
1928
1929#ifdef SUNOS4
1930#ifdef SPARC
1931
1932#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001933 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001934#endif
1935
1936 if (!(tcp->flags & TCB_BPTSET)) {
1937 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1938 return -1;
1939 }
1940 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1941 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1942 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1943 return -1;
1944 }
1945 tcp->flags &= ~TCB_BPTSET;
1946
1947#if !LOOPA
1948 /*
1949 * Since we don't have a single instruction breakpoint, we may have
1950 * to adjust the program counter after removing the our `breakpoint'.
1951 */
1952 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1953 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1954 return -1;
1955 }
1956 if ((regs.r_pc < tcp->baddr) ||
1957 (regs.r_pc > tcp->baddr + 4)) {
1958 /* The breakpoint has not been reached yet */
1959 if (debug)
1960 fprintf(stderr,
1961 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1962 regs.r_pc, tcp->parent->baddr);
1963 return 0;
1964 }
1965 if (regs.r_pc != tcp->baddr)
1966 if (debug)
1967 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1968 regs.r_pc, tcp->baddr);
1969
1970 regs.r_pc = tcp->baddr;
1971 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1972 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1973 return -1;
1974 }
1975#endif /* LOOPA */
1976#endif /* SPARC */
1977#endif /* SUNOS4 */
1978
1979 return 0;
1980}
1981
Roland McGrathd81f1d92003-01-09 06:53:34 +00001982#endif
1983
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001984#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001985
1986#ifdef SUNOS4
1987
1988static int
1989getex(pid, hdr)
1990int pid;
1991struct exec *hdr;
1992{
1993 int n;
1994
1995 for (n = 0; n < sizeof *hdr; n += 4) {
1996 long res;
1997 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1998 return -1;
1999 memcpy(((char *) hdr) + n, &res, 4);
2000 }
2001 if (debug) {
2002 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2003 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2004 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2005 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2006 }
2007 return 0;
2008}
2009
2010int
2011fixvfork(tcp)
2012struct tcb *tcp;
2013{
2014 int pid = tcp->pid;
2015 /*
2016 * Change `vfork' in a freshly exec'ed dynamically linked
2017 * executable's (internal) symbol table to plain old `fork'
2018 */
2019
2020 struct exec hdr;
2021 struct link_dynamic dyn;
2022 struct link_dynamic_2 ld;
2023 char *strtab, *cp;
2024
2025 if (getex(pid, &hdr) < 0)
2026 return -1;
2027 if (!hdr.a_dynamic)
2028 return -1;
2029
2030 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2031 fprintf(stderr, "Cannot read DYNAMIC\n");
2032 return -1;
2033 }
2034 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2035 fprintf(stderr, "Cannot read link_dynamic_2\n");
2036 return -1;
2037 }
2038 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002039 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 return -1;
2041 }
2042 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2043 (int)ld.ld_symb_size, strtab) < 0)
2044 goto err;
2045
2046#if 0
2047 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2048 fprintf(stderr, "[symbol: %s]\n", cp);
2049 cp += strlen(cp)+1;
2050 }
2051 return 0;
2052#endif
2053 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2054 if (strcmp(cp, "_vfork") == 0) {
2055 if (debug)
2056 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2057 strcpy(cp, "_fork");
2058 break;
2059 }
2060 cp += strlen(cp)+1;
2061 }
2062 if (cp < strtab + ld.ld_symb_size)
2063 /*
2064 * Write entire symbol table back to avoid
2065 * memory alignment bugs in ptrace
2066 */
2067 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2068 (int)ld.ld_symb_size, strtab) < 0)
2069 goto err;
2070
2071 free(strtab);
2072 return 0;
2073
2074err:
2075 free(strtab);
2076 return -1;
2077}
2078
2079#endif /* SUNOS4 */