blob: 470cec73b225fcca2545dcc764087a3fb99b7999 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046#ifdef SUNOS4
47#include <machine/reg.h>
48#include <a.out.h>
49#include <link.h>
50#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000051
Wichert Akkerman43a74822000-06-27 17:33:32 +000052#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Wichert Akkerman36915a11999-07-13 15:45:02 +000053#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000054#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000055
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000056#if defined(LINUX) && defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000057# include <asm/ptrace_offsets.h>
58# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000059#endif
60
Wichert Akkerman36915a11999-07-13 15:45:02 +000061#ifdef HAVE_SYS_REG_H
62#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000066# ifdef HAVE_STRUCT_IA64_FPREG
67# define ia64_fpreg XXX_ia64_fpreg
68# endif
69# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70# define pt_all_user_regs XXX_pt_all_user_regs
71# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000072#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000073# undef ia64_fpreg
74# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000075#endif
76
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78#include <sys/utsname.h>
79#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
Roland McGrath6d1a65c2004-07-12 07:44:08 +000081#if defined(LINUXSPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
Roland McGrath4db26242003-01-30 20:15:19 +000083# define fpq kernel_fpq
84# define fq kernel_fq
85# define fpu kernel_fpu
86# include <asm/reg.h>
87# undef fpq
88# undef fq
89# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000090
Roland McGrath6d1a65c2004-07-12 07:44:08 +000091#if defined (SPARC64)
92# define r_pc r_tpc
93# undef PTRACE_GETREGS
94# define PTRACE_GETREGS PTRACE_GETREGS64
95# undef PTRACE_SETREGS
96# define PTRACE_SETREGS PTRACE_SETREGS64
97#endif /* SPARC64 */
98
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000099#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100
101#include <linux/unistd.h>
102
103#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
106{ \
107 long __res; \
108\
109__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110 "or %%g0, %2, %%o1\n\t" \
111 "or %%g0, %3, %%o2\n\t" \
112 "or %%g0, %4, %%o3\n\t" \
113 "or %%g0, %5, %%o4\n\t" \
114 "or %%g0, %6, %%g1\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000115#if defined (SPARC64)
116 "t 0x6d\n\t" \
117#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118 "t 0x10\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000119#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 "bcc 1f\n\t" \
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
123 "1:\n\t" \
124 : "=r" (__res) \
125 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127 "i" (__NR_##syscall) \
128 : "g1", "o0", "o1", "o2", "o3", "o4"); \
129if (__res>=0) \
130 return (type) __res; \
131errno = -__res; \
132return -1; \
133}
134
135static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137#define _ptrace
138
139#endif
140
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000141#endif
142
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143/* macros */
144#ifndef MAX
145#define MAX(a,b) (((a) > (b)) ? (a) : (b))
146#endif
147#ifndef MIN
148#define MIN(a,b) (((a) < (b)) ? (a) : (b))
149#endif
150
Roland McGratha4d48532005-06-08 20:45:28 +0000151#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152void
153tv_tv(tv, a, b)
154struct timeval *tv;
155int a;
156int b;
157{
158 tv->tv_sec = a;
159 tv->tv_usec = b;
160}
Roland McGratha4d48532005-06-08 20:45:28 +0000161#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162
163int
164tv_nz(a)
165struct timeval *a;
166{
167 return a->tv_sec || a->tv_usec;
168}
169
170int
171tv_cmp(a, b)
172struct timeval *a, *b;
173{
174 if (a->tv_sec < b->tv_sec
175 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
176 return -1;
177 if (a->tv_sec > b->tv_sec
178 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
179 return 1;
180 return 0;
181}
182
183double
184tv_float(tv)
185struct timeval *tv;
186{
187 return tv->tv_sec + tv->tv_usec/1000000.0;
188}
189
190void
191tv_add(tv, a, b)
192struct timeval *tv, *a, *b;
193{
194 tv->tv_sec = a->tv_sec + b->tv_sec;
195 tv->tv_usec = a->tv_usec + b->tv_usec;
196 if (tv->tv_usec > 1000000) {
197 tv->tv_sec++;
198 tv->tv_usec -= 1000000;
199 }
200}
201
202void
203tv_sub(tv, a, b)
204struct timeval *tv, *a, *b;
205{
206 tv->tv_sec = a->tv_sec - b->tv_sec;
207 tv->tv_usec = a->tv_usec - b->tv_usec;
208 if (((long) tv->tv_usec) < 0) {
209 tv->tv_sec--;
210 tv->tv_usec += 1000000;
211 }
212}
213
214void
215tv_div(tv, a, n)
216struct timeval *tv, *a;
217int n;
218{
219 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
220 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
221 tv->tv_usec %= 1000000;
222}
223
224void
225tv_mul(tv, a, n)
226struct timeval *tv, *a;
227int n;
228{
229 tv->tv_usec = a->tv_usec * n;
230 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
231 tv->tv_usec %= 1000000;
232}
233
234char *
235xlookup(xlat, val)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000236const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237int val;
238{
239 for (; xlat->str != NULL; xlat++)
240 if (xlat->val == val)
241 return xlat->str;
242 return NULL;
243}
244
245/*
246 * Print entry in struct xlat table, if there.
247 */
248void
249printxval(xlat, val, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000250const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251int val;
Roland McGrathb2dee132005-06-01 19:02:36 +0000252const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000253{
254 char *str = xlookup(xlat, val);
255
256 if (str)
257 tprintf("%s", str);
258 else
259 tprintf("%#x /* %s */", val, dflt);
260}
261
262/*
263 * Interpret `xlat' as an array of flags
264 * print the entries whose bits are on in `flags'
265 * return # of flags printed.
266 */
267int
268addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000269const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000270int flags;
271{
272 int n;
273
274 for (n = 0; xlat->str; xlat++) {
275 if (xlat->val && (flags & xlat->val) == xlat->val) {
276 tprintf("|%s", xlat->str);
277 flags &= ~xlat->val;
278 n++;
279 }
280 }
281 if (flags) {
282 tprintf("|%#x", flags);
283 n++;
284 }
285 return n;
286}
287
288int
Roland McGrathb2dee132005-06-01 19:02:36 +0000289printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000290const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000291int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000292const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000293{
294 int n;
295 char *sep;
296
297 if (flags == 0 && xlat->val == 0) {
298 tprintf("%s", xlat->str);
299 return 1;
300 }
301
302 sep = "";
303 for (n = 0; xlat->str; xlat++) {
304 if (xlat->val && (flags & xlat->val) == xlat->val) {
305 tprintf("%s%s", sep, xlat->str);
306 flags &= ~xlat->val;
307 sep = "|";
308 n++;
309 }
310 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000311
312 if (n) {
313 if (flags) {
314 tprintf("%s%#x", sep, flags);
315 n++;
316 }
317 } else {
318 if (flags) {
319 tprintf("%#x", flags);
320 if (dflt)
321 tprintf(" /* %s */", dflt);
322 } else {
323 if (dflt)
324 tprintf("0");
325 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000327
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328 return n;
329}
330
331void
332printnum(tcp, addr, fmt)
333struct tcb *tcp;
334long addr;
335char *fmt;
336{
Roland McGratheb285352003-01-14 09:59:00 +0000337 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000338
339 if (!addr) {
340 tprintf("NULL");
341 return;
342 }
343 if (umove(tcp, addr, &num) < 0) {
344 tprintf("%#lx", addr);
345 return;
346 }
347 tprintf("[");
348 tprintf(fmt, num);
349 tprintf("]");
350}
351
Roland McGrath6bc12202003-11-13 22:32:27 +0000352void
Roland McGrath9814a942005-07-04 23:28:10 +0000353printnum_int(tcp, addr, fmt)
354struct tcb *tcp;
355long addr;
356char *fmt;
357{
358 int num;
359
360 if (!addr) {
361 tprintf("NULL");
362 return;
363 }
364 if (umove(tcp, addr, &num) < 0) {
365 tprintf("%#lx", addr);
366 return;
367 }
368 tprintf("[");
369 tprintf(fmt, num);
370 tprintf("]");
371}
372
373void
Roland McGrath6bc12202003-11-13 22:32:27 +0000374printuid(text, uid)
375const char *text;
376unsigned long uid;
377{
378 tprintf("%s", text);
379 tprintf((uid == -1) ? "%ld" : "%lu", uid);
380}
381
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382static char path[MAXPATHLEN + 1];
383
Roland McGratha4d48532005-06-08 20:45:28 +0000384static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385string_quote(str)
Roland McGratha4d48532005-06-08 20:45:28 +0000386const char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387{
388 char buf[2 * MAXPATHLEN + 1];
389 char *s;
390
391 if (!strpbrk(str, "\"\'\\")) {
392 tprintf("\"%s\"", str);
393 return;
394 }
395 for (s = buf; *str; str++) {
396 switch (*str) {
397 case '\"': case '\'': case '\\':
398 *s++ = '\\'; *s++ = *str; break;
399 default:
400 *s++ = *str; break;
401 }
402 }
403 *s = '\0';
404 tprintf("\"%s\"", buf);
405}
406
407void
408printpath(tcp, addr)
409struct tcb *tcp;
410long addr;
411{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000412 if (addr == 0)
413 tprintf("NULL");
414 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000415 tprintf("%#lx", addr);
416 else
417 string_quote(path);
418 return;
419}
420
421void
422printpathn(tcp, addr, n)
423struct tcb *tcp;
424long addr;
425int n;
426{
Roland McGrathb15c4e42005-10-21 22:06:46 +0000427 if (n >= sizeof path)
428 n = sizeof path - 1;
429
Roland McGrath371ed8f2005-02-06 01:55:07 +0000430 if (addr == 0)
431 tprintf("NULL");
432 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433 tprintf("%#lx", addr);
434 else {
435 path[n] = '\0';
436 string_quote(path);
437 }
438}
439
440void
441printstr(tcp, addr, len)
442struct tcb *tcp;
443long addr;
444int len;
445{
446 static unsigned char *str = NULL;
447 static char *outstr;
448 int i, n, c, usehex;
449 char *s, *outend;
450
451 if (!addr) {
452 tprintf("NULL");
453 return;
454 }
455 if (!str) {
456 if ((str = malloc(max_strlen)) == NULL
457 || (outstr = malloc(2*max_strlen)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000458 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000459 tprintf("%#lx", addr);
460 return;
461 }
462 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000463 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000464 if (len < 0) {
465 n = max_strlen;
466 if (umovestr(tcp, addr, n, (char *) str) < 0) {
467 tprintf("%#lx", addr);
468 return;
469 }
470 }
471 else {
472 n = MIN(len, max_strlen);
473 if (umoven(tcp, addr, n, (char *) str) < 0) {
474 tprintf("%#lx", addr);
475 return;
476 }
477 }
478
479 usehex = 0;
480 if (xflag > 1)
481 usehex = 1;
482 else if (xflag) {
483 for (i = 0; i < n; i++) {
484 c = str[i];
485 if (len < 0 && c == '\0')
486 break;
487 if (!isprint(c) && !isspace(c)) {
488 usehex = 1;
489 break;
490 }
491 }
492 }
493
494 s = outstr;
495 *s++ = '\"';
496
497 if (usehex) {
498 for (i = 0; i < n; i++) {
499 c = str[i];
500 if (len < 0 && c == '\0')
501 break;
502 sprintf(s, "\\x%02x", c);
503 s += 4;
504 if (s > outend)
505 break;
506 }
507 }
508 else {
509 for (i = 0; i < n; i++) {
510 c = str[i];
511 if (len < 0 && c == '\0')
512 break;
513 switch (c) {
514 case '\"': case '\'': case '\\':
515 *s++ = '\\'; *s++ = c; break;
516 case '\f':
517 *s++ = '\\'; *s++ = 'f'; break;
518 case '\n':
519 *s++ = '\\'; *s++ = 'n'; break;
520 case '\r':
521 *s++ = '\\'; *s++ = 'r'; break;
522 case '\t':
523 *s++ = '\\'; *s++ = 't'; break;
524 case '\v':
525 *s++ = '\\'; *s++ = 'v'; break;
526 default:
527 if (isprint(c))
528 *s++ = c;
529 else if (i < n - 1 && isdigit(str[i + 1])) {
530 sprintf(s, "\\%03o", c);
531 s += 4;
532 }
533 else {
534 sprintf(s, "\\%o", c);
535 s += strlen(s);
536 }
537 break;
538 }
539 if (s > outend)
540 break;
541 }
542 }
543
544 *s++ = '\"';
545 if (i < len || (len < 0 && (i == n || s > outend))) {
546 *s++ = '.'; *s++ = '.'; *s++ = '.';
547 }
548 *s = '\0';
549 tprintf("%s", outstr);
550}
551
John Hughes1d08dcf2001-07-10 13:48:44 +0000552#if HAVE_SYS_UIO_H
553void
554dumpiov(tcp, len, addr)
555struct tcb * tcp;
556int len;
557long addr;
558{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000559#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
560 union {
561 struct { u_int32_t base; u_int32_t len; } *iov32;
562 struct { u_int64_t base; u_int64_t len; } *iov64;
563 } iovu;
564#define iov iovu.iov64
565#define sizeof_iov \
566 (personality_wordsize[current_personality] == 4 \
567 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
568#define iov_iov_base(i) \
569 (personality_wordsize[current_personality] == 4 \
570 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
571#define iov_iov_len(i) \
572 (personality_wordsize[current_personality] == 4 \
573 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
574#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000575 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000576#define sizeof_iov sizeof(*iov)
577#define iov_iov_base(i) iov[i].iov_base
578#define iov_iov_len(i) iov[i].iov_len
579#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000580 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000581 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000582
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000583 size = sizeof_iov * (unsigned long) len;
584 if (size / sizeof_iov != len
585 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000586 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000587 return;
588 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000589 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000590 for (i = 0; i < len; i++) {
591 /* include the buffer number to make it easy to
592 * match up the trace with the source */
593 tprintf(" * %lu bytes in buffer %d\n",
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000594 (unsigned long)iov_iov_len(i), i);
595 dumpstr(tcp, (long) iov_iov_base(i),
596 iov_iov_len(i));
John Hughes1d08dcf2001-07-10 13:48:44 +0000597 }
598 }
599 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000600#undef sizeof_iov
601#undef iov_iov_base
602#undef iov_iov_len
603#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000604}
605#endif
606
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607void
608dumpstr(tcp, addr, len)
609struct tcb *tcp;
610long addr;
611int len;
612{
613 static int strsize = -1;
614 static unsigned char *str;
615 static char outstr[80];
616 char *s;
617 int i, j;
618
619 if (strsize < len) {
620 if (str)
621 free(str);
622 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000623 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000624 return;
625 }
626 strsize = len;
627 }
628
629 if (umoven(tcp, addr, len, (char *) str) < 0)
630 return;
631
632 for (i = 0; i < len; i += 16) {
633 s = outstr;
634 sprintf(s, " | %05x ", i);
635 s += 9;
636 for (j = 0; j < 16; j++) {
637 if (j == 8)
638 *s++ = ' ';
639 if (i + j < len) {
640 sprintf(s, " %02x", str[i + j]);
641 s += 3;
642 }
643 else {
644 *s++ = ' '; *s++ = ' '; *s++ = ' ';
645 }
646 }
647 *s++ = ' '; *s++ = ' ';
648 for (j = 0; j < 16; j++) {
649 if (j == 8)
650 *s++ = ' ';
651 if (i + j < len) {
652 if (isprint(str[i + j]))
653 *s++ = str[i + j];
654 else
655 *s++ = '.';
656 }
657 else
658 *s++ = ' ';
659 }
660 tprintf("%s |\n", outstr);
661 }
662}
663
664#define PAGMASK (~(PAGSIZ - 1))
665/*
666 * move `len' bytes of data from process `pid'
667 * at address `addr' to our space at `laddr'
668 */
669int
670umoven(tcp, addr, len, laddr)
671struct tcb *tcp;
672long addr;
673int len;
674char *laddr;
675{
676
677#ifdef LINUX
678 int pid = tcp->pid;
679 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000680 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000681 union {
682 long val;
683 char x[sizeof(long)];
684 } u;
685
686 if (addr & (sizeof(long) - 1)) {
687 /* addr not a multiple of sizeof(long) */
688 n = addr - (addr & -sizeof(long)); /* residue */
689 addr &= -sizeof(long); /* residue */
690 errno = 0;
691 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
692 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000693 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000694 /* Ran into 'end of memory' - stupid "printpath" */
695 return 0;
696 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000697 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000698 perror("ptrace: umoven");
699 return -1;
700 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000701 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000702 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
703 addr += sizeof(long), laddr += m, len -= m;
704 }
705 while (len) {
706 errno = 0;
707 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
708 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000709 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000710 /* Ran into 'end of memory' - stupid "printpath" */
711 return 0;
712 }
Roland McGrath4db26242003-01-30 20:15:19 +0000713 if (addr != 0)
714 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 return -1;
716 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000717 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
719 addr += sizeof(long), laddr += m, len -= m;
720 }
721#endif /* LINUX */
722
723#ifdef SUNOS4
724 int pid = tcp->pid;
725#if 0
726 int n, m;
727 union {
728 long val;
729 char x[sizeof(long)];
730 } u;
731
732 if (addr & (sizeof(long) - 1)) {
733 /* addr not a multiple of sizeof(long) */
734 n = addr - (addr & -sizeof(long)); /* residue */
735 addr &= -sizeof(long); /* residue */
736 errno = 0;
737 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
738 if (errno) {
739 perror("umoven");
740 return -1;
741 }
742 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
743 addr += sizeof(long), laddr += m, len -= m;
744 }
745 while (len) {
746 errno = 0;
747 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
748 if (errno) {
749 perror("umoven");
750 return -1;
751 }
752 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
753 addr += sizeof(long), laddr += m, len -= m;
754 }
755#else /* !oldway */
756 int n;
757
758 while (len) {
759 n = MIN(len, PAGSIZ);
760 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
761 if (ptrace(PTRACE_READDATA, pid,
762 (char *) addr, len, laddr) < 0) {
763 perror("umoven: ptrace(PTRACE_READDATA, ...)");
764 abort();
765 return -1;
766 }
767 len -= n;
768 addr += n;
769 laddr += n;
770 }
771#endif /* !oldway */
772#endif /* SUNOS4 */
773
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000774#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000775#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000776 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000777#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000778 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000780 lseek(fd, addr, SEEK_SET);
781 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000782 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000783#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000784
785 return 0;
786}
787
788/*
789 * like `umove' but make the additional effort of looking
790 * for a terminating zero byte.
791 */
792int
793umovestr(tcp, addr, len, laddr)
794struct tcb *tcp;
795long addr;
796int len;
797char *laddr;
798{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000799#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000800#ifdef HAVE_MP_PROCFS
801 int fd = tcp->pfd_as;
802#else
803 int fd = tcp->pfd;
804#endif
805 /* Some systems (e.g. FreeBSD) can be upset if we read off the
806 end of valid memory, avoid this by trying to read up
807 to page boundaries. But we don't know what a page is (and
808 getpagesize(2) (if it exists) doesn't necessarily return
809 hardware page size). Assume all pages >= 1024 (a-historical
810 I know) */
811
812 int page = 1024; /* How to find this? */
813 int move = page - (addr & (page - 1));
814 int left = len;
815
816 lseek(fd, addr, SEEK_SET);
817
818 while (left) {
819 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000820 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000821 return left != len ? 0 : -1;
822 if (memchr (laddr, 0, move)) break;
823 left -= move;
824 laddr += move;
825 addr += move;
826 move = page;
827 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000828#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000829 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830 int pid = tcp->pid;
831 int i, n, m;
832 union {
833 long val;
834 char x[sizeof(long)];
835 } u;
836
837 if (addr & (sizeof(long) - 1)) {
838 /* addr not a multiple of sizeof(long) */
839 n = addr - (addr & -sizeof(long)); /* residue */
840 addr &= -sizeof(long); /* residue */
841 errno = 0;
842 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
843 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000844 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845 /* Ran into 'end of memory' - stupid "printpath" */
846 return 0;
847 }
848 perror("umovestr");
849 return -1;
850 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000851 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000852 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
853 while (n & (sizeof(long) - 1))
854 if (u.x[n++] == '\0')
855 return 0;
856 addr += sizeof(long), laddr += m, len -= m;
857 }
858 while (len) {
859 errno = 0;
860 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
861 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000862 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000863 /* Ran into 'end of memory' - stupid "printpath" */
864 return 0;
865 }
866 perror("umovestr");
867 return -1;
868 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000869 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000870 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
871 for (i = 0; i < sizeof(long); i++)
872 if (u.x[i] == '\0')
873 return 0;
874
875 addr += sizeof(long), laddr += m, len -= m;
876 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000877#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000878 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879}
880
881#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000882#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883#define PTRACE_WRITETEXT 101
884#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000885#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000886#endif /* LINUX */
887
888#ifdef SUNOS4
889
890static int
891uload(cmd, pid, addr, len, laddr)
892int cmd;
893int pid;
894long addr;
895int len;
896char *laddr;
897{
898#if 0
899 int n;
900
901 while (len) {
902 n = MIN(len, PAGSIZ);
903 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
904 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
905 perror("uload: ptrace(PTRACE_WRITE, ...)");
906 return -1;
907 }
908 len -= n;
909 addr += n;
910 laddr += n;
911 }
912#else
913 int peek, poke;
914 int n, m;
915 union {
916 long val;
917 char x[sizeof(long)];
918 } u;
919
920 if (cmd == PTRACE_WRITETEXT) {
921 peek = PTRACE_PEEKTEXT;
922 poke = PTRACE_POKETEXT;
923 }
924 else {
925 peek = PTRACE_PEEKDATA;
926 poke = PTRACE_POKEDATA;
927 }
928 if (addr & (sizeof(long) - 1)) {
929 /* addr not a multiple of sizeof(long) */
930 n = addr - (addr & -sizeof(long)); /* residue */
931 addr &= -sizeof(long);
932 errno = 0;
933 u.val = ptrace(peek, pid, (char *) addr, 0);
934 if (errno) {
935 perror("uload: POKE");
936 return -1;
937 }
938 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
939 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
940 perror("uload: POKE");
941 return -1;
942 }
943 addr += sizeof(long), laddr += m, len -= m;
944 }
945 while (len) {
946 if (len < sizeof(long))
947 u.val = ptrace(peek, pid, (char *) addr, 0);
948 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
949 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
950 perror("uload: POKE");
951 return -1;
952 }
953 addr += sizeof(long), laddr += m, len -= m;
954 }
955#endif
956 return 0;
957}
958
959int
960tload(pid, addr, len, laddr)
961int pid;
962int addr, len;
963char *laddr;
964{
965 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
966}
967
968int
969dload(pid, addr, len, laddr)
970int pid;
971int addr;
972int len;
973char *laddr;
974{
975 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
976}
977
978#endif /* SUNOS4 */
979
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000980#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000981
982int
983upeek(pid, off, res)
984int pid;
985long off;
986long *res;
987{
988 long val;
989
990#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
991 {
992 static int is_sun4m = -1;
993 struct utsname name;
994
995 /* Round up the usual suspects. */
996 if (is_sun4m == -1) {
997 if (uname(&name) < 0) {
998 perror("upeek: uname?");
999 exit(1);
1000 }
1001 is_sun4m = strcmp(name.machine, "sun4m") == 0;
1002 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +00001003 extern const struct xlat struct_user_offsets[];
1004 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005
1006 for (x = struct_user_offsets; x->str; x++)
1007 x->val += 1024;
1008 }
1009 }
1010 if (is_sun4m)
1011 off += 1024;
1012 }
1013#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1014 errno = 0;
1015 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1016 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +00001017 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +00001018 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +00001019 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001020 return -1;
1021 }
1022 *res = val;
1023 return 0;
1024}
1025
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001026#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027
Roland McGratha4d48532005-06-08 20:45:28 +00001028#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001029long
1030getpc(tcp)
1031struct tcb *tcp;
1032{
1033
1034#ifdef LINUX
1035 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001036#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1038 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001039#elif defined(X86_64)
1040 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1041 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001042#elif defined(IA64)
1043 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1044 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001045#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 if (upeek(tcp->pid, 4*15, &pc) < 0)
1047 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001048#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001049 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001051#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001052 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1053 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001054#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001055 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1056 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001057#elif defined(MIPS)
1058 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1059 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001060#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001061 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001062 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1063 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001064 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001065#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001066 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001067 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001068#elif defined(HPPA)
1069 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1070 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001071#elif defined(SH)
1072 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1073 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001074#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001075 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1076 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001077#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001078 return pc;
1079#endif /* LINUX */
1080
1081#ifdef SUNOS4
1082 /*
1083 * Return current program counter for `pid'
1084 * Assumes PC is never 0xffffffff
1085 */
1086 struct regs regs;
1087
1088 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1089 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1090 return -1;
1091 }
1092 return regs.r_pc;
1093#endif /* SUNOS4 */
1094
1095#ifdef SVR4
1096 /* XXX */
1097 return 0;
1098#endif /* SVR4 */
1099
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001100#ifdef FREEBSD
1101 struct reg regs;
1102 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1103 return regs.r_eip;
1104#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105}
Roland McGratha4d48532005-06-08 20:45:28 +00001106#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107
1108void
1109printcall(tcp)
1110struct tcb *tcp;
1111{
Roland McGrath7a918832005-02-02 20:55:23 +00001112#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1113 sizeof(long) == 8 ? "[????????????????] " : \
1114 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001115
1116#ifdef LINUX
1117#ifdef I386
1118 long eip;
1119
1120 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001121 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122 return;
1123 }
1124 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001125
1126#elif defined(S390) || defined(S390X)
1127 long psw;
1128 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001129 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001130 return;
1131 }
1132#ifdef S390
1133 tprintf("[%08lx] ", psw);
1134#elif S390X
1135 tprintf("[%16lx] ", psw);
1136#endif
1137
Michal Ludvig0e035502002-09-23 15:41:01 +00001138#elif defined(X86_64)
1139 long rip;
1140
1141 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001142 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001143 return;
1144 }
1145 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001146#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001147 long ip;
1148
1149 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001150 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001151 return;
1152 }
1153 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001154#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 long pc;
1156
Roland McGratheb285352003-01-14 09:59:00 +00001157 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 tprintf ("[????????] ");
1159 return;
1160 }
1161 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001162#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 long pc;
1164
1165 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1166 tprintf ("[????????] ");
1167 return;
1168 }
1169 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001170#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171 long pc;
1172
1173 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001174 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 return;
1176 }
1177 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001178#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001179 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001180 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001181 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 return;
1183 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001184 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001185#elif defined(HPPA)
1186 long pc;
1187
1188 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1189 tprintf ("[????????] ");
1190 return;
1191 }
1192 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001193#elif defined(MIPS)
1194 long pc;
1195
1196 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1197 tprintf ("[????????] ");
1198 return;
1199 }
1200 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001201#elif defined(SH)
1202 long pc;
1203
1204 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1205 tprintf ("[????????] ");
1206 return;
1207 }
1208 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001209#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001210 long pc;
1211
1212 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001213 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001214 return;
1215 }
1216 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001217#elif defined(ARM)
1218 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001219
Roland McGrathef388682003-06-03 23:28:59 +00001220 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001221 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001222 return;
1223 }
1224 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001225#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226#endif /* LINUX */
1227
1228#ifdef SUNOS4
1229 struct regs regs;
1230
1231 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1232 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001233 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001234 return;
1235 }
1236 tprintf("[%08x] ", regs.r_o7);
1237#endif /* SUNOS4 */
1238
1239#ifdef SVR4
1240 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001241 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242#endif
1243
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001244#ifdef FREEBSD
1245 struct reg regs;
1246 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1247 tprintf("[%08x] ", regs.r_eip);
1248#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249}
1250
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001251#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001252
Roland McGrathd81f1d92003-01-09 06:53:34 +00001253#if defined LINUX
1254
1255#include <sys/syscall.h>
1256#ifndef CLONE_PTRACE
1257# define CLONE_PTRACE 0x00002000
1258#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001259#ifndef CLONE_STOPPED
1260# define CLONE_STOPPED 0x02000000
1261#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262
1263#ifdef IA64
1264
Roland McGrath08267b82004-02-20 22:56:43 +00001265/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1266 subsystem has them for x86... */
1267#define SYS_fork 2
1268#define SYS_vfork 190
1269
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270typedef unsigned long *arg_setup_state;
1271
1272static int
1273arg_setup(struct tcb *tcp, arg_setup_state *state)
1274{
1275 unsigned long *bsp, cfm, sof, sol;
1276
Roland McGrath08267b82004-02-20 22:56:43 +00001277 if (ia32)
1278 return 0;
1279
Roland McGrathd81f1d92003-01-09 06:53:34 +00001280 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1281 return -1;
1282 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1283 return -1;
1284
1285 sof = (cfm >> 0) & 0x7f;
1286 sol = (cfm >> 7) & 0x7f;
1287 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1288
1289 *state = bsp;
1290 return 0;
1291}
1292
1293# define arg_finish_change(tcp, state) 0
1294
1295#ifdef SYS_fork
1296static int
1297get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1298{
Roland McGrath08267b82004-02-20 22:56:43 +00001299 int ret;
1300
1301 if (ia32)
1302 ret = upeek (tcp->pid, PT_R11, valp);
1303 else
1304 ret = umoven (tcp,
1305 (unsigned long) ia64_rse_skip_regs(*state, 0),
1306 sizeof(long), (void *) valp);
1307 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001308}
1309
1310static int
1311get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1312{
Roland McGrath08267b82004-02-20 22:56:43 +00001313 int ret;
1314
1315 if (ia32)
1316 ret = upeek (tcp->pid, PT_R9, valp);
1317 else
1318 ret = umoven (tcp,
1319 (unsigned long) ia64_rse_skip_regs(*state, 1),
1320 sizeof(long), (void *) valp);
1321 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001322}
1323#endif
1324
1325static int
1326set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1327{
Roland McGrath08267b82004-02-20 22:56:43 +00001328 int req = PTRACE_POKEDATA;
1329 void *ap;
1330
1331 if (ia32) {
1332 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1333 req = PTRACE_POKEUSER;
1334 } else
1335 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001336 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001337 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338 return errno ? -1 : 0;
1339}
1340
1341static int
1342set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1343{
Roland McGrath08267b82004-02-20 22:56:43 +00001344 int req = PTRACE_POKEDATA;
1345 void *ap;
1346
1347 if (ia32) {
1348 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1349 req = PTRACE_POKEUSER;
1350 } else
1351 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001352 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001353 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001354 return errno ? -1 : 0;
1355}
1356
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001357#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001358
1359typedef struct regs arg_setup_state;
1360
1361# define arg_setup(tcp, state) \
1362 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1363# define arg_finish_change(tcp, state) \
1364 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1365
1366# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1367# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1368# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1369# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001370# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001371
1372#else
1373
1374# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001375/* Note: this is only true for the `clone' system call, which handles
1376 arguments specially. We could as well say that its first two arguments
1377 are swapped relative to other architectures, but that would just be
1378 another #ifdef in the calls. */
1379# define arg0_offset PT_GPR3
1380# define arg1_offset PT_ORIGGPR2
1381# define restore_arg0(tcp, state, val) ((void) (state), 0)
1382# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001383# define arg0_index 1
1384# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001385# elif defined (ALPHA) || defined (MIPS)
1386# define arg0_offset REG_A0
1387# define arg1_offset (REG_A0+1)
1388# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001389# define arg0_offset (sizeof(unsigned long)*PT_R3)
1390# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001391# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001392# elif defined (HPPA)
1393# define arg0_offset PT_GR26
1394# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001395# elif defined (X86_64)
1396# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1397# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001398# elif defined (SH)
1399# define arg0_offset (4*(REG_REG0+4))
1400# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001401# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001402 /* ABI defines arg0 & 1 in r2 & r3 */
1403# define arg0_offset (REG_OFFSET+16)
1404# define arg1_offset (REG_OFFSET+24)
1405# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001406# else
1407# define arg0_offset 0
1408# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001409# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001410# define restore_arg0(tcp, state, val) 0
1411# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001412# endif
1413
1414typedef int arg_setup_state;
1415
1416# define arg_setup(tcp, state) (0)
1417# define arg_finish_change(tcp, state) 0
1418# define get_arg0(tcp, cookie, valp) \
1419 (upeek ((tcp)->pid, arg0_offset, (valp)))
1420# define get_arg1(tcp, cookie, valp) \
1421 (upeek ((tcp)->pid, arg1_offset, (valp)))
1422
1423static int
1424set_arg0 (struct tcb *tcp, void *cookie, long val)
1425{
Roland McGrathca85b972005-06-07 23:22:08 +00001426 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001427}
1428
1429static int
1430set_arg1 (struct tcb *tcp, void *cookie, long val)
1431{
1432 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1433}
1434
1435#endif
1436
Roland McGrathe1df47f2003-01-14 09:46:15 +00001437#ifndef restore_arg0
1438# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1439#endif
1440#ifndef restore_arg1
1441# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1442#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001443
Roland McGrath90d0afd2004-03-01 21:05:16 +00001444#ifndef arg0_index
1445# define arg0_index 0
1446# define arg1_index 1
1447#endif
1448
Roland McGrathd81f1d92003-01-09 06:53:34 +00001449int
1450setbpt(tcp)
1451struct tcb *tcp;
1452{
1453 extern int change_syscall(struct tcb *, int);
1454 arg_setup_state state;
1455
1456 if (tcp->flags & TCB_BPTSET) {
1457 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1458 return -1;
1459 }
1460
Roland McGrath76989d72005-06-07 23:21:31 +00001461 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001462#ifdef SYS_vfork
1463 case SYS_vfork:
1464#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001465#ifdef SYS_fork
1466 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001467#endif
1468#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001469 if (arg_setup (tcp, &state) < 0
1470 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1471 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1472 || change_syscall(tcp, SYS_clone) < 0
1473 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1474 || set_arg1 (tcp, &state, 0) < 0
1475 || arg_finish_change (tcp, &state) < 0)
1476 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001477 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1478 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001479 tcp->flags |= TCB_BPTSET;
1480 return 0;
1481#endif
1482
1483 case SYS_clone:
1484#ifdef SYS_clone2
1485 case SYS_clone2:
1486#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001487 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001488 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001489 || set_arg0 (tcp, &state,
1490 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001491 || arg_finish_change (tcp, &state) < 0))
1492 return -1;
1493 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001494 tcp->inst[0] = tcp->u_arg[arg0_index];
1495 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001496 return 0;
1497
1498 default:
1499 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1500 tcp->scno, tcp->pid);
1501 break;
1502 }
1503
1504 return -1;
1505}
1506
1507int
1508clearbpt(tcp)
1509struct tcb *tcp;
1510{
1511 arg_setup_state state;
1512 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001513 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1514 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001515 || arg_finish_change (tcp, &state))
1516 return -1;
1517 tcp->flags &= ~TCB_BPTSET;
1518 return 0;
1519}
1520
1521#else
1522
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523int
1524setbpt(tcp)
1525struct tcb *tcp;
1526{
1527
1528#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001529#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530 /* We simply use the SunOS breakpoint code. */
1531
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001532 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001533 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534#define LOOPA 0x30800000 /* ba,a 0 */
1535
1536 if (tcp->flags & TCB_BPTSET) {
1537 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1538 return -1;
1539 }
1540 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1541 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1542 return -1;
1543 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001544 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545 errno = 0;
1546 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1547 if(errno) {
1548 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1549 return -1;
1550 }
1551
1552 /*
1553 * XXX - BRUTAL MODE ON
1554 * We cannot set a real BPT in the child, since it will not be
1555 * traced at the moment it will reach the trap and would probably
1556 * die with a core dump.
1557 * Thus, we are force our way in by taking out two instructions
1558 * and insert an eternal loop instead, in expectance of the SIGSTOP
1559 * generated by out PTRACE_ATTACH.
1560 * Of cause, if we evaporate ourselves in the middle of all this...
1561 */
1562 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001563 inst = LOOPA;
1564#if defined (SPARC64)
1565 inst <<= 32;
1566 inst |= (tcp->inst[0] & 0xffffffffUL);
1567#endif
1568 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569 if(errno) {
1570 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1571 return -1;
1572 }
1573 tcp->flags |= TCB_BPTSET;
1574
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001575#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001576#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001577 if (ia32) {
1578# define LOOP 0x0000feeb
1579 if (tcp->flags & TCB_BPTSET) {
1580 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1581 tcp->pid);
1582 return -1;
1583 }
1584 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1585 return -1;
1586 if (debug)
1587 fprintf(stderr, "[%d] setting bpt at %lx\n",
1588 tcp->pid, tcp->baddr);
1589 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1590 (char *) tcp->baddr, 0);
1591 if (errno) {
1592 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1593 return -1;
1594 }
1595 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1596 if (errno) {
1597 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1598 return -1;
1599 }
1600 tcp->flags |= TCB_BPTSET;
1601 } else {
1602 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001603 * Our strategy here is to replace the bundle that
1604 * contained the clone() syscall with a bundle of the
1605 * form:
1606 *
1607 * { 1: br 1b; br 1b; br 1b }
1608 *
1609 * This ensures that the newly forked child will loop
1610 * endlessly until we've got a chance to attach to it.
1611 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001612# define LOOP0 0x0000100000000017
1613# define LOOP1 0x4000000000200000
1614 unsigned long addr, ipsr;
1615 pid_t pid;
1616
1617 pid = tcp->pid;
1618 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1619 return -1;
1620 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1621 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001622 /* store "ri" in low two bits */
1623 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001624
1625 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001626 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1627 0);
1628 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1629 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001630 if (errno) {
1631 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1632 return -1;
1633 }
1634
1635 errno = 0;
1636 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1637 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1638 if (errno) {
1639 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1640 return -1;
1641 }
1642 tcp->flags |= TCB_BPTSET;
1643 }
1644#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645
Michal Ludvig0e035502002-09-23 15:41:01 +00001646#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647#define LOOP 0x0000feeb
1648#elif defined (M68K)
1649#define LOOP 0x60fe0000
1650#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001651#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001653#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001654#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001655#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001656#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001657#define LOOP 0x1000ffff
1658#elif defined(S390)
1659#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001660#elif defined(S390X)
1661#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001662#elif defined(HPPA)
1663#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001664#elif defined(SH)
1665#ifdef __LITTLE_ENDIAN__
1666#define LOOP 0x0000affe
1667#else
1668#define LOOP 0xfeaf0000
1669#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670#else
1671#error unknown architecture
1672#endif
1673
1674 if (tcp->flags & TCB_BPTSET) {
1675 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1676 return -1;
1677 }
1678#if defined (I386)
1679 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1680 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001681#elif defined (X86_64)
1682 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1683 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684#elif defined (M68K)
1685 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1686 return -1;
1687#elif defined (ALPHA)
1688 return -1;
1689#elif defined (ARM)
1690 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001691#elif defined (MIPS)
1692 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001693#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001694 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001695 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001696#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001697 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1698 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001699#elif defined(HPPA)
1700 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1701 return -1;
1702 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001703#elif defined(SH)
1704 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1705 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001706#else
1707#error unknown architecture
1708#endif
1709 if (debug)
1710 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1711 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1712 if (errno) {
1713 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1714 return -1;
1715 }
1716 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1717 if (errno) {
1718 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1719 return -1;
1720 }
1721 tcp->flags |= TCB_BPTSET;
1722
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001723#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001724#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725#endif /* LINUX */
1726
1727#ifdef SUNOS4
1728#ifdef SPARC /* This code is slightly sparc specific */
1729
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001730 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001731#define BPT 0x91d02001 /* ta 1 */
1732#define LOOP 0x10800000 /* ba 0 */
1733#define LOOPA 0x30800000 /* ba,a 0 */
1734#define NOP 0x01000000
1735#if LOOPA
1736 static int loopdeloop[1] = {LOOPA};
1737#else
1738 static int loopdeloop[2] = {LOOP, NOP};
1739#endif
1740
1741 if (tcp->flags & TCB_BPTSET) {
1742 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1743 return -1;
1744 }
1745 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1746 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1747 return -1;
1748 }
1749 tcp->baddr = regs.r_o7 + 8;
1750 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1751 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1752 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1753 return -1;
1754 }
1755
1756 /*
1757 * XXX - BRUTAL MODE ON
1758 * We cannot set a real BPT in the child, since it will not be
1759 * traced at the moment it will reach the trap and would probably
1760 * die with a core dump.
1761 * Thus, we are force our way in by taking out two instructions
1762 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1763 * generated by out PTRACE_ATTACH.
1764 * Of cause, if we evaporate ourselves in the middle of all this...
1765 */
1766 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1767 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1768 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1769 return -1;
1770 }
1771 tcp->flags |= TCB_BPTSET;
1772
1773#endif /* SPARC */
1774#endif /* SUNOS4 */
1775
1776 return 0;
1777}
1778
1779int
1780clearbpt(tcp)
1781struct tcb *tcp;
1782{
1783
1784#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001785#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001787#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001788 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001789#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001790 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001791#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001792 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001793#elif defined(HPPA)
1794 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001795#elif defined(SH)
1796 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001797#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001798
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001799#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800 /* Again, we borrow the SunOS breakpoint code. */
1801 if (!(tcp->flags & TCB_BPTSET)) {
1802 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1803 return -1;
1804 }
1805 errno = 0;
1806 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1807 if(errno) {
1808 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1809 return -1;
1810 }
1811 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001812#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001813 if (ia32) {
1814 unsigned long addr;
1815
1816 if (debug)
1817 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1818 if (!(tcp->flags & TCB_BPTSET)) {
1819 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1820 return -1;
1821 }
1822 errno = 0;
1823 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1824 if (errno) {
1825 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1826 return -1;
1827 }
1828 tcp->flags &= ~TCB_BPTSET;
1829
1830 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1831 return -1;
1832 if (addr != tcp->baddr) {
1833 /* The breakpoint has not been reached yet. */
1834 if (debug)
1835 fprintf(stderr,
1836 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1837 addr, tcp->baddr);
1838 return 0;
1839 }
1840 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001841 unsigned long addr, ipsr;
1842 pid_t pid;
1843
1844 pid = tcp->pid;
1845
1846 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1847 return -1;
1848 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1849 return -1;
1850
1851 /* restore original bundle: */
1852 errno = 0;
1853 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1854 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1855 if (errno) {
1856 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1857 return -1;
1858 }
1859
1860 /* restore original "ri" in ipsr: */
1861 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1862 errno = 0;
1863 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1864 if (errno) {
1865 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1866 return -1;
1867 }
1868
1869 tcp->flags &= ~TCB_BPTSET;
1870
1871 if (addr != (tcp->baddr & ~0x3)) {
1872 /* the breakpoint has not been reached yet. */
1873 if (debug)
1874 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1875 addr, tcp->baddr);
1876 return 0;
1877 }
1878 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001879#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880
1881 if (debug)
1882 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1883 if (!(tcp->flags & TCB_BPTSET)) {
1884 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1885 return -1;
1886 }
1887 errno = 0;
1888 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1889 if (errno) {
1890 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1891 return -1;
1892 }
1893 tcp->flags &= ~TCB_BPTSET;
1894
1895#ifdef I386
1896 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1897 return -1;
1898 if (eip != tcp->baddr) {
1899 /* The breakpoint has not been reached yet. */
1900 if (debug)
1901 fprintf(stderr,
1902 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1903 eip, tcp->baddr);
1904 return 0;
1905 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001906#elif defined(X86_64)
1907 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1908 return -1;
1909 if (eip != tcp->baddr) {
1910 /* The breakpoint has not been reached yet. */
1911 if (debug)
1912 fprintf(stderr,
1913 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1914 eip, tcp->baddr);
1915 return 0;
1916 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001917#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001918 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001919 return -1;
1920 if (pc != tcp->baddr) {
1921 /* The breakpoint has not been reached yet. */
1922 if (debug)
1923 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1924 pc, tcp->baddr);
1925 return 0;
1926 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001927#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001928 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1929 return -1;
1930 if (pc != tcp->baddr) {
1931 /* The breakpoint has not been reached yet. */
1932 if (debug)
1933 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1934 pc, tcp->baddr);
1935 return 0;
1936 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001937#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001938 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1939 return -1;
1940 if (pc != tcp->baddr) {
1941 /* The breakpoint has not been reached yet. */
1942 if (debug)
1943 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1944 pc, tcp->baddr);
1945 return 0;
1946 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001947#elif defined(HPPA)
1948 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1949 return -1;
1950 iaoq &= ~0x03;
1951 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1952 /* The breakpoint has not been reached yet. */
1953 if (debug)
1954 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1955 iaoq, tcp->baddr);
1956 return 0;
1957 }
1958 iaoq = tcp->baddr | 3;
1959 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1960 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1961 * has no significant effect.
1962 */
1963 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1964 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001965#elif defined(SH)
1966 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1967 return -1;
1968 if (pc != tcp->baddr) {
1969 /* The breakpoint has not been reached yet. */
1970 if (debug)
1971 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1972 pc, tcp->baddr);
1973 return 0;
1974 }
1975
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001976#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001977#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001978#endif /* LINUX */
1979
1980#ifdef SUNOS4
1981#ifdef SPARC
1982
1983#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001984 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001985#endif
1986
1987 if (!(tcp->flags & TCB_BPTSET)) {
1988 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1989 return -1;
1990 }
1991 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1992 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1993 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1994 return -1;
1995 }
1996 tcp->flags &= ~TCB_BPTSET;
1997
1998#if !LOOPA
1999 /*
2000 * Since we don't have a single instruction breakpoint, we may have
2001 * to adjust the program counter after removing the our `breakpoint'.
2002 */
2003 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2004 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2005 return -1;
2006 }
2007 if ((regs.r_pc < tcp->baddr) ||
2008 (regs.r_pc > tcp->baddr + 4)) {
2009 /* The breakpoint has not been reached yet */
2010 if (debug)
2011 fprintf(stderr,
2012 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2013 regs.r_pc, tcp->parent->baddr);
2014 return 0;
2015 }
2016 if (regs.r_pc != tcp->baddr)
2017 if (debug)
2018 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2019 regs.r_pc, tcp->baddr);
2020
2021 regs.r_pc = tcp->baddr;
2022 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2023 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2024 return -1;
2025 }
2026#endif /* LOOPA */
2027#endif /* SPARC */
2028#endif /* SUNOS4 */
2029
2030 return 0;
2031}
2032
Roland McGrathd81f1d92003-01-09 06:53:34 +00002033#endif
2034
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002035#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002036
2037#ifdef SUNOS4
2038
2039static int
2040getex(pid, hdr)
2041int pid;
2042struct exec *hdr;
2043{
2044 int n;
2045
2046 for (n = 0; n < sizeof *hdr; n += 4) {
2047 long res;
2048 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2049 return -1;
2050 memcpy(((char *) hdr) + n, &res, 4);
2051 }
2052 if (debug) {
2053 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2054 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2055 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2056 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2057 }
2058 return 0;
2059}
2060
2061int
2062fixvfork(tcp)
2063struct tcb *tcp;
2064{
2065 int pid = tcp->pid;
2066 /*
2067 * Change `vfork' in a freshly exec'ed dynamically linked
2068 * executable's (internal) symbol table to plain old `fork'
2069 */
2070
2071 struct exec hdr;
2072 struct link_dynamic dyn;
2073 struct link_dynamic_2 ld;
2074 char *strtab, *cp;
2075
2076 if (getex(pid, &hdr) < 0)
2077 return -1;
2078 if (!hdr.a_dynamic)
2079 return -1;
2080
2081 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2082 fprintf(stderr, "Cannot read DYNAMIC\n");
2083 return -1;
2084 }
2085 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2086 fprintf(stderr, "Cannot read link_dynamic_2\n");
2087 return -1;
2088 }
2089 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002090 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002091 return -1;
2092 }
2093 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2094 (int)ld.ld_symb_size, strtab) < 0)
2095 goto err;
2096
2097#if 0
2098 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2099 fprintf(stderr, "[symbol: %s]\n", cp);
2100 cp += strlen(cp)+1;
2101 }
2102 return 0;
2103#endif
2104 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2105 if (strcmp(cp, "_vfork") == 0) {
2106 if (debug)
2107 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2108 strcpy(cp, "_fork");
2109 break;
2110 }
2111 cp += strlen(cp)+1;
2112 }
2113 if (cp < strtab + ld.ld_symb_size)
2114 /*
2115 * Write entire symbol table back to avoid
2116 * memory alignment bugs in ptrace
2117 */
2118 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2119 (int)ld.ld_symb_size, strtab) < 0)
2120 goto err;
2121
2122 free(strtab);
2123 return 0;
2124
2125err:
2126 free(strtab);
2127 return -1;
2128}
2129
2130#endif /* SUNOS4 */