blob: 06162f4121238be74e034518e111d812a78cd08b [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
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000234const char *
235xlookup(const struct xlat *xlat, int val)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236{
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
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000247printxval(const struct xlat *xlat, int val, const char *dflt)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248{
Dmitry V. Levinab9008b2007-01-11 22:05:04 +0000249 const char *str = xlookup(xlat, val);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250
251 if (str)
252 tprintf("%s", str);
253 else
254 tprintf("%#x /* %s */", val, dflt);
255}
256
257/*
258 * Interpret `xlat' as an array of flags
259 * print the entries whose bits are on in `flags'
260 * return # of flags printed.
261 */
262int
263addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000264const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000265int flags;
266{
267 int n;
268
269 for (n = 0; xlat->str; xlat++) {
270 if (xlat->val && (flags & xlat->val) == xlat->val) {
271 tprintf("|%s", xlat->str);
272 flags &= ~xlat->val;
273 n++;
274 }
275 }
276 if (flags) {
277 tprintf("|%#x", flags);
278 n++;
279 }
280 return n;
281}
282
283int
Roland McGrathb2dee132005-06-01 19:02:36 +0000284printflags(xlat, flags, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000285const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000286int flags;
Roland McGrathb2dee132005-06-01 19:02:36 +0000287const char *dflt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000288{
289 int n;
290 char *sep;
291
292 if (flags == 0 && xlat->val == 0) {
293 tprintf("%s", xlat->str);
294 return 1;
295 }
296
297 sep = "";
298 for (n = 0; xlat->str; xlat++) {
299 if (xlat->val && (flags & xlat->val) == xlat->val) {
300 tprintf("%s%s", sep, xlat->str);
301 flags &= ~xlat->val;
302 sep = "|";
303 n++;
304 }
305 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000306
307 if (n) {
308 if (flags) {
309 tprintf("%s%#x", sep, flags);
310 n++;
311 }
312 } else {
313 if (flags) {
314 tprintf("%#x", flags);
315 if (dflt)
316 tprintf(" /* %s */", dflt);
317 } else {
318 if (dflt)
319 tprintf("0");
320 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 }
Roland McGrathb2dee132005-06-01 19:02:36 +0000322
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000323 return n;
324}
325
326void
327printnum(tcp, addr, fmt)
328struct tcb *tcp;
329long addr;
330char *fmt;
331{
Roland McGratheb285352003-01-14 09:59:00 +0000332 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333
334 if (!addr) {
335 tprintf("NULL");
336 return;
337 }
338 if (umove(tcp, addr, &num) < 0) {
339 tprintf("%#lx", addr);
340 return;
341 }
342 tprintf("[");
343 tprintf(fmt, num);
344 tprintf("]");
345}
346
Roland McGrath6bc12202003-11-13 22:32:27 +0000347void
Roland McGrath9814a942005-07-04 23:28:10 +0000348printnum_int(tcp, addr, fmt)
349struct tcb *tcp;
350long addr;
351char *fmt;
352{
353 int num;
354
355 if (!addr) {
356 tprintf("NULL");
357 return;
358 }
359 if (umove(tcp, addr, &num) < 0) {
360 tprintf("%#lx", addr);
361 return;
362 }
363 tprintf("[");
364 tprintf(fmt, num);
365 tprintf("]");
366}
367
368void
Roland McGrath6bc12202003-11-13 22:32:27 +0000369printuid(text, uid)
370const char *text;
371unsigned long uid;
372{
373 tprintf("%s", text);
374 tprintf((uid == -1) ? "%ld" : "%lu", uid);
375}
376
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000377static char path[MAXPATHLEN + 1];
378
Roland McGratha4d48532005-06-08 20:45:28 +0000379static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000380string_quote(str)
Roland McGratha4d48532005-06-08 20:45:28 +0000381const char *str;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382{
383 char buf[2 * MAXPATHLEN + 1];
384 char *s;
385
386 if (!strpbrk(str, "\"\'\\")) {
387 tprintf("\"%s\"", str);
388 return;
389 }
390 for (s = buf; *str; str++) {
391 switch (*str) {
392 case '\"': case '\'': case '\\':
393 *s++ = '\\'; *s++ = *str; break;
394 default:
395 *s++ = *str; break;
396 }
397 }
398 *s = '\0';
399 tprintf("\"%s\"", buf);
400}
401
402void
403printpath(tcp, addr)
404struct tcb *tcp;
405long addr;
406{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000407 if (addr == 0)
408 tprintf("NULL");
409 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000410 tprintf("%#lx", addr);
411 else
412 string_quote(path);
413 return;
414}
415
416void
417printpathn(tcp, addr, n)
418struct tcb *tcp;
419long addr;
420int n;
421{
Roland McGrathb15c4e42005-10-21 22:06:46 +0000422 if (n >= sizeof path)
423 n = sizeof path - 1;
424
Roland McGrath371ed8f2005-02-06 01:55:07 +0000425 if (addr == 0)
426 tprintf("NULL");
427 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000428 tprintf("%#lx", addr);
429 else {
430 path[n] = '\0';
431 string_quote(path);
432 }
433}
434
435void
436printstr(tcp, addr, len)
437struct tcb *tcp;
438long addr;
439int len;
440{
441 static unsigned char *str = NULL;
442 static char *outstr;
443 int i, n, c, usehex;
444 char *s, *outend;
445
446 if (!addr) {
447 tprintf("NULL");
448 return;
449 }
450 if (!str) {
451 if ((str = malloc(max_strlen)) == NULL
452 || (outstr = malloc(2*max_strlen)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000453 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000454 tprintf("%#lx", addr);
455 return;
456 }
457 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000458 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000459 if (len < 0) {
460 n = max_strlen;
461 if (umovestr(tcp, addr, n, (char *) str) < 0) {
462 tprintf("%#lx", addr);
463 return;
464 }
465 }
466 else {
467 n = MIN(len, max_strlen);
468 if (umoven(tcp, addr, n, (char *) str) < 0) {
469 tprintf("%#lx", addr);
470 return;
471 }
472 }
473
474 usehex = 0;
475 if (xflag > 1)
476 usehex = 1;
477 else if (xflag) {
478 for (i = 0; i < n; i++) {
479 c = str[i];
480 if (len < 0 && c == '\0')
481 break;
482 if (!isprint(c) && !isspace(c)) {
483 usehex = 1;
484 break;
485 }
486 }
487 }
488
489 s = outstr;
490 *s++ = '\"';
491
492 if (usehex) {
493 for (i = 0; i < n; i++) {
494 c = str[i];
495 if (len < 0 && c == '\0')
496 break;
497 sprintf(s, "\\x%02x", c);
498 s += 4;
499 if (s > outend)
500 break;
501 }
502 }
503 else {
504 for (i = 0; i < n; i++) {
505 c = str[i];
506 if (len < 0 && c == '\0')
507 break;
508 switch (c) {
509 case '\"': case '\'': case '\\':
510 *s++ = '\\'; *s++ = c; break;
511 case '\f':
512 *s++ = '\\'; *s++ = 'f'; break;
513 case '\n':
514 *s++ = '\\'; *s++ = 'n'; break;
515 case '\r':
516 *s++ = '\\'; *s++ = 'r'; break;
517 case '\t':
518 *s++ = '\\'; *s++ = 't'; break;
519 case '\v':
520 *s++ = '\\'; *s++ = 'v'; break;
521 default:
522 if (isprint(c))
523 *s++ = c;
524 else if (i < n - 1 && isdigit(str[i + 1])) {
525 sprintf(s, "\\%03o", c);
526 s += 4;
527 }
528 else {
529 sprintf(s, "\\%o", c);
530 s += strlen(s);
531 }
532 break;
533 }
534 if (s > outend)
535 break;
536 }
537 }
538
539 *s++ = '\"';
540 if (i < len || (len < 0 && (i == n || s > outend))) {
541 *s++ = '.'; *s++ = '.'; *s++ = '.';
542 }
543 *s = '\0';
544 tprintf("%s", outstr);
545}
546
John Hughes1d08dcf2001-07-10 13:48:44 +0000547#if HAVE_SYS_UIO_H
548void
549dumpiov(tcp, len, addr)
550struct tcb * tcp;
551int len;
552long addr;
553{
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000554#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
555 union {
556 struct { u_int32_t base; u_int32_t len; } *iov32;
557 struct { u_int64_t base; u_int64_t len; } *iov64;
558 } iovu;
559#define iov iovu.iov64
560#define sizeof_iov \
561 (personality_wordsize[current_personality] == 4 \
562 ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
563#define iov_iov_base(i) \
564 (personality_wordsize[current_personality] == 4 \
565 ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
566#define iov_iov_len(i) \
567 (personality_wordsize[current_personality] == 4 \
568 ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
569#else
John Hughes1d08dcf2001-07-10 13:48:44 +0000570 struct iovec *iov;
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000571#define sizeof_iov sizeof(*iov)
572#define iov_iov_base(i) iov[i].iov_base
573#define iov_iov_len(i) iov[i].iov_len
574#endif
John Hughes1d08dcf2001-07-10 13:48:44 +0000575 int i;
Roland McGrathaa524c82005-06-01 19:22:06 +0000576 unsigned long size;
John Hughes1d08dcf2001-07-10 13:48:44 +0000577
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000578 size = sizeof_iov * (unsigned long) len;
579 if (size / sizeof_iov != len
580 || (iov = malloc(size)) == NULL) {
Roland McGrathaa524c82005-06-01 19:22:06 +0000581 fprintf(stderr, "out of memory\n");
John Hughes1d08dcf2001-07-10 13:48:44 +0000582 return;
583 }
Roland McGrathaa524c82005-06-01 19:22:06 +0000584 if (umoven(tcp, addr, size, (char *) iov) >= 0) {
John Hughes1d08dcf2001-07-10 13:48:44 +0000585 for (i = 0; i < len; i++) {
586 /* include the buffer number to make it easy to
587 * match up the trace with the source */
588 tprintf(" * %lu bytes in buffer %d\n",
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000589 (unsigned long)iov_iov_len(i), i);
590 dumpstr(tcp, (long) iov_iov_base(i),
591 iov_iov_len(i));
John Hughes1d08dcf2001-07-10 13:48:44 +0000592 }
593 }
594 free((char *) iov);
Dmitry V. Levin4ebb4e32006-12-13 17:08:08 +0000595#undef sizeof_iov
596#undef iov_iov_base
597#undef iov_iov_len
598#undef iov
John Hughes1d08dcf2001-07-10 13:48:44 +0000599}
600#endif
601
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602void
603dumpstr(tcp, addr, len)
604struct tcb *tcp;
605long addr;
606int len;
607{
608 static int strsize = -1;
609 static unsigned char *str;
610 static char outstr[80];
611 char *s;
612 int i, j;
613
614 if (strsize < len) {
615 if (str)
616 free(str);
617 if ((str = malloc(len)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +0000618 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000619 return;
620 }
621 strsize = len;
622 }
623
624 if (umoven(tcp, addr, len, (char *) str) < 0)
625 return;
626
627 for (i = 0; i < len; i += 16) {
628 s = outstr;
629 sprintf(s, " | %05x ", i);
630 s += 9;
631 for (j = 0; j < 16; j++) {
632 if (j == 8)
633 *s++ = ' ';
634 if (i + j < len) {
635 sprintf(s, " %02x", str[i + j]);
636 s += 3;
637 }
638 else {
639 *s++ = ' '; *s++ = ' '; *s++ = ' ';
640 }
641 }
642 *s++ = ' '; *s++ = ' ';
643 for (j = 0; j < 16; j++) {
644 if (j == 8)
645 *s++ = ' ';
646 if (i + j < len) {
647 if (isprint(str[i + j]))
648 *s++ = str[i + j];
649 else
650 *s++ = '.';
651 }
652 else
653 *s++ = ' ';
654 }
655 tprintf("%s |\n", outstr);
656 }
657}
658
659#define PAGMASK (~(PAGSIZ - 1))
660/*
661 * move `len' bytes of data from process `pid'
662 * at address `addr' to our space at `laddr'
663 */
664int
665umoven(tcp, addr, len, laddr)
666struct tcb *tcp;
667long addr;
668int len;
669char *laddr;
670{
671
672#ifdef LINUX
673 int pid = tcp->pid;
674 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000675 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676 union {
677 long val;
678 char x[sizeof(long)];
679 } u;
680
681 if (addr & (sizeof(long) - 1)) {
682 /* addr not a multiple of sizeof(long) */
683 n = addr - (addr & -sizeof(long)); /* residue */
684 addr &= -sizeof(long); /* residue */
685 errno = 0;
686 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
687 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000688 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689 /* Ran into 'end of memory' - stupid "printpath" */
690 return 0;
691 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000692 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693 perror("ptrace: umoven");
694 return -1;
695 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000696 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
698 addr += sizeof(long), laddr += m, len -= m;
699 }
700 while (len) {
701 errno = 0;
702 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
703 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000704 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705 /* Ran into 'end of memory' - stupid "printpath" */
706 return 0;
707 }
Roland McGrath4db26242003-01-30 20:15:19 +0000708 if (addr != 0)
709 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000710 return -1;
711 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000712 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000713 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
714 addr += sizeof(long), laddr += m, len -= m;
715 }
716#endif /* LINUX */
717
718#ifdef SUNOS4
719 int pid = tcp->pid;
720#if 0
721 int n, m;
722 union {
723 long val;
724 char x[sizeof(long)];
725 } u;
726
727 if (addr & (sizeof(long) - 1)) {
728 /* addr not a multiple of sizeof(long) */
729 n = addr - (addr & -sizeof(long)); /* residue */
730 addr &= -sizeof(long); /* residue */
731 errno = 0;
732 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
733 if (errno) {
734 perror("umoven");
735 return -1;
736 }
737 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
738 addr += sizeof(long), laddr += m, len -= m;
739 }
740 while (len) {
741 errno = 0;
742 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
743 if (errno) {
744 perror("umoven");
745 return -1;
746 }
747 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
748 addr += sizeof(long), laddr += m, len -= m;
749 }
750#else /* !oldway */
751 int n;
752
753 while (len) {
754 n = MIN(len, PAGSIZ);
755 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
756 if (ptrace(PTRACE_READDATA, pid,
757 (char *) addr, len, laddr) < 0) {
758 perror("umoven: ptrace(PTRACE_READDATA, ...)");
759 abort();
760 return -1;
761 }
762 len -= n;
763 addr += n;
764 laddr += n;
765 }
766#endif /* !oldway */
767#endif /* SUNOS4 */
768
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000769#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000770#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000771 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000772#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000773 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000774#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000775 lseek(fd, addr, SEEK_SET);
776 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000777 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000778#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779
780 return 0;
781}
782
783/*
784 * like `umove' but make the additional effort of looking
785 * for a terminating zero byte.
786 */
787int
788umovestr(tcp, addr, len, laddr)
789struct tcb *tcp;
790long addr;
791int len;
792char *laddr;
793{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000794#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000795#ifdef HAVE_MP_PROCFS
796 int fd = tcp->pfd_as;
797#else
798 int fd = tcp->pfd;
799#endif
800 /* Some systems (e.g. FreeBSD) can be upset if we read off the
801 end of valid memory, avoid this by trying to read up
802 to page boundaries. But we don't know what a page is (and
803 getpagesize(2) (if it exists) doesn't necessarily return
804 hardware page size). Assume all pages >= 1024 (a-historical
805 I know) */
806
807 int page = 1024; /* How to find this? */
808 int move = page - (addr & (page - 1));
809 int left = len;
810
811 lseek(fd, addr, SEEK_SET);
812
813 while (left) {
814 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000815 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000816 return left != len ? 0 : -1;
817 if (memchr (laddr, 0, move)) break;
818 left -= move;
819 laddr += move;
820 addr += move;
821 move = page;
822 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000823#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000824 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000825 int pid = tcp->pid;
826 int i, n, m;
827 union {
828 long val;
829 char x[sizeof(long)];
830 } u;
831
832 if (addr & (sizeof(long) - 1)) {
833 /* addr not a multiple of sizeof(long) */
834 n = addr - (addr & -sizeof(long)); /* residue */
835 addr &= -sizeof(long); /* residue */
836 errno = 0;
837 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
838 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000839 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000840 /* Ran into 'end of memory' - stupid "printpath" */
841 return 0;
842 }
843 perror("umovestr");
844 return -1;
845 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000846 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000847 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
848 while (n & (sizeof(long) - 1))
849 if (u.x[n++] == '\0')
850 return 0;
851 addr += sizeof(long), laddr += m, len -= m;
852 }
853 while (len) {
854 errno = 0;
855 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
856 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000857 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000858 /* Ran into 'end of memory' - stupid "printpath" */
859 return 0;
860 }
861 perror("umovestr");
862 return -1;
863 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000864 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000865 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
866 for (i = 0; i < sizeof(long); i++)
867 if (u.x[i] == '\0')
868 return 0;
869
870 addr += sizeof(long), laddr += m, len -= m;
871 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000872#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000873 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000874}
875
876#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000877#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878#define PTRACE_WRITETEXT 101
879#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000880#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881#endif /* LINUX */
882
883#ifdef SUNOS4
884
885static int
886uload(cmd, pid, addr, len, laddr)
887int cmd;
888int pid;
889long addr;
890int len;
891char *laddr;
892{
893#if 0
894 int n;
895
896 while (len) {
897 n = MIN(len, PAGSIZ);
898 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
899 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
900 perror("uload: ptrace(PTRACE_WRITE, ...)");
901 return -1;
902 }
903 len -= n;
904 addr += n;
905 laddr += n;
906 }
907#else
908 int peek, poke;
909 int n, m;
910 union {
911 long val;
912 char x[sizeof(long)];
913 } u;
914
915 if (cmd == PTRACE_WRITETEXT) {
916 peek = PTRACE_PEEKTEXT;
917 poke = PTRACE_POKETEXT;
918 }
919 else {
920 peek = PTRACE_PEEKDATA;
921 poke = PTRACE_POKEDATA;
922 }
923 if (addr & (sizeof(long) - 1)) {
924 /* addr not a multiple of sizeof(long) */
925 n = addr - (addr & -sizeof(long)); /* residue */
926 addr &= -sizeof(long);
927 errno = 0;
928 u.val = ptrace(peek, pid, (char *) addr, 0);
929 if (errno) {
930 perror("uload: POKE");
931 return -1;
932 }
933 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
934 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
935 perror("uload: POKE");
936 return -1;
937 }
938 addr += sizeof(long), laddr += m, len -= m;
939 }
940 while (len) {
941 if (len < sizeof(long))
942 u.val = ptrace(peek, pid, (char *) addr, 0);
943 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
944 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
945 perror("uload: POKE");
946 return -1;
947 }
948 addr += sizeof(long), laddr += m, len -= m;
949 }
950#endif
951 return 0;
952}
953
954int
955tload(pid, addr, len, laddr)
956int pid;
957int addr, len;
958char *laddr;
959{
960 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
961}
962
963int
964dload(pid, addr, len, laddr)
965int pid;
966int addr;
967int len;
968char *laddr;
969{
970 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
971}
972
973#endif /* SUNOS4 */
974
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000975#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000976
977int
978upeek(pid, off, res)
979int pid;
980long off;
981long *res;
982{
983 long val;
984
985#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
986 {
987 static int is_sun4m = -1;
988 struct utsname name;
989
990 /* Round up the usual suspects. */
991 if (is_sun4m == -1) {
992 if (uname(&name) < 0) {
993 perror("upeek: uname?");
994 exit(1);
995 }
996 is_sun4m = strcmp(name.machine, "sun4m") == 0;
997 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000998 extern const struct xlat struct_user_offsets[];
999 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000
1001 for (x = struct_user_offsets; x->str; x++)
1002 x->val += 1024;
1003 }
1004 }
1005 if (is_sun4m)
1006 off += 1024;
1007 }
1008#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1009 errno = 0;
1010 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
1011 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +00001012 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +00001013 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +00001014 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001015 return -1;
1016 }
1017 *res = val;
1018 return 0;
1019}
1020
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001021#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022
Roland McGratha4d48532005-06-08 20:45:28 +00001023#if 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001024long
1025getpc(tcp)
1026struct tcb *tcp;
1027{
1028
1029#ifdef LINUX
1030 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001031#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
1033 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001034#elif defined(X86_64)
1035 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
1036 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001037#elif defined(IA64)
1038 if (upeek(tcp->pid, PT_B0, &pc) < 0)
1039 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001040#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 if (upeek(tcp->pid, 4*15, &pc) < 0)
1042 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001043#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001044 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045 return -1;
Roland McGrath84fa9232005-06-08 18:06:22 +00001046#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1048 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001049#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1051 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001052#elif defined(MIPS)
1053 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
1054 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001055#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001056 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1058 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001059 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001060#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001061 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001062 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001063#elif defined(HPPA)
1064 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1065 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001066#elif defined(SH)
1067 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1068 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001069#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001070 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1071 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001072#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073 return pc;
1074#endif /* LINUX */
1075
1076#ifdef SUNOS4
1077 /*
1078 * Return current program counter for `pid'
1079 * Assumes PC is never 0xffffffff
1080 */
1081 struct regs regs;
1082
1083 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1084 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1085 return -1;
1086 }
1087 return regs.r_pc;
1088#endif /* SUNOS4 */
1089
1090#ifdef SVR4
1091 /* XXX */
1092 return 0;
1093#endif /* SVR4 */
1094
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001095#ifdef FREEBSD
1096 struct reg regs;
1097 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1098 return regs.r_eip;
1099#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001100}
Roland McGratha4d48532005-06-08 20:45:28 +00001101#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001102
1103void
1104printcall(tcp)
1105struct tcb *tcp;
1106{
Roland McGrath7a918832005-02-02 20:55:23 +00001107#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1108 sizeof(long) == 8 ? "[????????????????] " : \
1109 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110
1111#ifdef LINUX
1112#ifdef I386
1113 long eip;
1114
1115 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001116 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 return;
1118 }
1119 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001120
1121#elif defined(S390) || defined(S390X)
1122 long psw;
1123 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001124 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001125 return;
1126 }
1127#ifdef S390
1128 tprintf("[%08lx] ", psw);
1129#elif S390X
1130 tprintf("[%16lx] ", psw);
1131#endif
1132
Michal Ludvig0e035502002-09-23 15:41:01 +00001133#elif defined(X86_64)
1134 long rip;
1135
1136 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001137 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001138 return;
1139 }
1140 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001141#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001142 long ip;
1143
1144 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001145 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001146 return;
1147 }
1148 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001149#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 long pc;
1151
Roland McGratheb285352003-01-14 09:59:00 +00001152 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 tprintf ("[????????] ");
1154 return;
1155 }
1156 tprintf("[%08lx] ", pc);
Roland McGrath84fa9232005-06-08 18:06:22 +00001157#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 long pc;
1159
1160 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1161 tprintf ("[????????] ");
1162 return;
1163 }
1164 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001165#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 long pc;
1167
1168 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001169 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 return;
1171 }
1172 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001173#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001174 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001176 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 return;
1178 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001179 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001180#elif defined(HPPA)
1181 long pc;
1182
1183 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1184 tprintf ("[????????] ");
1185 return;
1186 }
1187 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001188#elif defined(MIPS)
1189 long pc;
1190
1191 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1192 tprintf ("[????????] ");
1193 return;
1194 }
1195 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001196#elif defined(SH)
1197 long pc;
1198
1199 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1200 tprintf ("[????????] ");
1201 return;
1202 }
1203 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001204#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001205 long pc;
1206
1207 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001208 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001209 return;
1210 }
1211 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001212#elif defined(ARM)
1213 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001214
Roland McGrathef388682003-06-03 23:28:59 +00001215 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001216 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001217 return;
1218 }
1219 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001220#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221#endif /* LINUX */
1222
1223#ifdef SUNOS4
1224 struct regs regs;
1225
1226 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1227 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001228 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 return;
1230 }
1231 tprintf("[%08x] ", regs.r_o7);
1232#endif /* SUNOS4 */
1233
1234#ifdef SVR4
1235 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001236 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237#endif
1238
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001239#ifdef FREEBSD
1240 struct reg regs;
1241 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1242 tprintf("[%08x] ", regs.r_eip);
1243#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001244}
1245
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001246#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247
Roland McGrathd81f1d92003-01-09 06:53:34 +00001248#if defined LINUX
1249
1250#include <sys/syscall.h>
1251#ifndef CLONE_PTRACE
1252# define CLONE_PTRACE 0x00002000
1253#endif
Roland McGrath76989d72005-06-07 23:21:31 +00001254#ifndef CLONE_STOPPED
1255# define CLONE_STOPPED 0x02000000
1256#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001257
1258#ifdef IA64
1259
Roland McGrath08267b82004-02-20 22:56:43 +00001260/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1261 subsystem has them for x86... */
1262#define SYS_fork 2
1263#define SYS_vfork 190
1264
Roland McGrathd81f1d92003-01-09 06:53:34 +00001265typedef unsigned long *arg_setup_state;
1266
1267static int
1268arg_setup(struct tcb *tcp, arg_setup_state *state)
1269{
1270 unsigned long *bsp, cfm, sof, sol;
1271
Roland McGrath08267b82004-02-20 22:56:43 +00001272 if (ia32)
1273 return 0;
1274
Roland McGrathd81f1d92003-01-09 06:53:34 +00001275 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1276 return -1;
1277 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1278 return -1;
1279
1280 sof = (cfm >> 0) & 0x7f;
1281 sol = (cfm >> 7) & 0x7f;
1282 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1283
1284 *state = bsp;
1285 return 0;
1286}
1287
1288# define arg_finish_change(tcp, state) 0
1289
1290#ifdef SYS_fork
1291static int
1292get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1293{
Roland McGrath08267b82004-02-20 22:56:43 +00001294 int ret;
1295
1296 if (ia32)
1297 ret = upeek (tcp->pid, PT_R11, valp);
1298 else
1299 ret = umoven (tcp,
1300 (unsigned long) ia64_rse_skip_regs(*state, 0),
1301 sizeof(long), (void *) valp);
1302 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001303}
1304
1305static int
1306get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1307{
Roland McGrath08267b82004-02-20 22:56:43 +00001308 int ret;
1309
1310 if (ia32)
1311 ret = upeek (tcp->pid, PT_R9, valp);
1312 else
1313 ret = umoven (tcp,
1314 (unsigned long) ia64_rse_skip_regs(*state, 1),
1315 sizeof(long), (void *) valp);
1316 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001317}
1318#endif
1319
1320static int
1321set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1322{
Roland McGrath08267b82004-02-20 22:56:43 +00001323 int req = PTRACE_POKEDATA;
1324 void *ap;
1325
1326 if (ia32) {
1327 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1328 req = PTRACE_POKEUSER;
1329 } else
1330 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001331 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001332 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001333 return errno ? -1 : 0;
1334}
1335
1336static int
1337set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1338{
Roland McGrath08267b82004-02-20 22:56:43 +00001339 int req = PTRACE_POKEDATA;
1340 void *ap;
1341
1342 if (ia32) {
1343 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1344 req = PTRACE_POKEUSER;
1345 } else
1346 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001347 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001348 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001349 return errno ? -1 : 0;
1350}
1351
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001352#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001353
1354typedef struct regs arg_setup_state;
1355
1356# define arg_setup(tcp, state) \
1357 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1358# define arg_finish_change(tcp, state) \
1359 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1360
1361# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1362# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1363# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1364# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001365# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001366
1367#else
1368
1369# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001370/* Note: this is only true for the `clone' system call, which handles
1371 arguments specially. We could as well say that its first two arguments
1372 are swapped relative to other architectures, but that would just be
1373 another #ifdef in the calls. */
1374# define arg0_offset PT_GPR3
1375# define arg1_offset PT_ORIGGPR2
1376# define restore_arg0(tcp, state, val) ((void) (state), 0)
1377# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001378# define arg0_index 1
1379# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001380# elif defined (ALPHA) || defined (MIPS)
1381# define arg0_offset REG_A0
1382# define arg1_offset (REG_A0+1)
1383# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001384# define arg0_offset (sizeof(unsigned long)*PT_R3)
1385# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001386# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001387# elif defined (HPPA)
1388# define arg0_offset PT_GR26
1389# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001390# elif defined (X86_64)
1391# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1392# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001393# elif defined (SH)
1394# define arg0_offset (4*(REG_REG0+4))
1395# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001396# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001397 /* ABI defines arg0 & 1 in r2 & r3 */
1398# define arg0_offset (REG_OFFSET+16)
1399# define arg1_offset (REG_OFFSET+24)
1400# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401# else
1402# define arg0_offset 0
1403# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001404# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001405# define restore_arg0(tcp, state, val) 0
1406# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001407# endif
1408
1409typedef int arg_setup_state;
1410
1411# define arg_setup(tcp, state) (0)
1412# define arg_finish_change(tcp, state) 0
1413# define get_arg0(tcp, cookie, valp) \
1414 (upeek ((tcp)->pid, arg0_offset, (valp)))
1415# define get_arg1(tcp, cookie, valp) \
1416 (upeek ((tcp)->pid, arg1_offset, (valp)))
1417
1418static int
1419set_arg0 (struct tcb *tcp, void *cookie, long val)
1420{
Roland McGrathca85b972005-06-07 23:22:08 +00001421 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001422}
1423
1424static int
1425set_arg1 (struct tcb *tcp, void *cookie, long val)
1426{
1427 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1428}
1429
1430#endif
1431
Roland McGrathe1df47f2003-01-14 09:46:15 +00001432#ifndef restore_arg0
1433# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1434#endif
1435#ifndef restore_arg1
1436# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1437#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001438
Roland McGrath90d0afd2004-03-01 21:05:16 +00001439#ifndef arg0_index
1440# define arg0_index 0
1441# define arg1_index 1
1442#endif
1443
Roland McGrathd81f1d92003-01-09 06:53:34 +00001444int
1445setbpt(tcp)
1446struct tcb *tcp;
1447{
1448 extern int change_syscall(struct tcb *, int);
1449 arg_setup_state state;
1450
1451 if (tcp->flags & TCB_BPTSET) {
1452 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1453 return -1;
1454 }
1455
Roland McGrath76989d72005-06-07 23:21:31 +00001456 switch (known_scno(tcp)) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001457#ifdef SYS_vfork
1458 case SYS_vfork:
1459#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001460#ifdef SYS_fork
1461 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001462#endif
1463#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001464 if (arg_setup (tcp, &state) < 0
1465 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1466 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1467 || change_syscall(tcp, SYS_clone) < 0
1468 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1469 || set_arg1 (tcp, &state, 0) < 0
1470 || arg_finish_change (tcp, &state) < 0)
1471 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001472 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1473 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001474 tcp->flags |= TCB_BPTSET;
1475 return 0;
1476#endif
1477
1478 case SYS_clone:
1479#ifdef SYS_clone2
1480 case SYS_clone2:
1481#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001482 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001483 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001484 || set_arg0 (tcp, &state,
1485 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001486 || arg_finish_change (tcp, &state) < 0))
1487 return -1;
1488 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001489 tcp->inst[0] = tcp->u_arg[arg0_index];
1490 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001491 return 0;
1492
1493 default:
1494 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1495 tcp->scno, tcp->pid);
1496 break;
1497 }
1498
1499 return -1;
1500}
1501
1502int
1503clearbpt(tcp)
1504struct tcb *tcp;
1505{
1506 arg_setup_state state;
1507 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001508 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1509 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001510 || arg_finish_change (tcp, &state))
1511 return -1;
1512 tcp->flags &= ~TCB_BPTSET;
1513 return 0;
1514}
1515
1516#else
1517
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518int
1519setbpt(tcp)
1520struct tcb *tcp;
1521{
1522
1523#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001524#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525 /* We simply use the SunOS breakpoint code. */
1526
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001527 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001528 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529#define LOOPA 0x30800000 /* ba,a 0 */
1530
1531 if (tcp->flags & TCB_BPTSET) {
1532 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1533 return -1;
1534 }
1535 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1536 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1537 return -1;
1538 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001539 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540 errno = 0;
1541 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1542 if(errno) {
1543 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1544 return -1;
1545 }
1546
1547 /*
1548 * XXX - BRUTAL MODE ON
1549 * We cannot set a real BPT in the child, since it will not be
1550 * traced at the moment it will reach the trap and would probably
1551 * die with a core dump.
1552 * Thus, we are force our way in by taking out two instructions
1553 * and insert an eternal loop instead, in expectance of the SIGSTOP
1554 * generated by out PTRACE_ATTACH.
1555 * Of cause, if we evaporate ourselves in the middle of all this...
1556 */
1557 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001558 inst = LOOPA;
1559#if defined (SPARC64)
1560 inst <<= 32;
1561 inst |= (tcp->inst[0] & 0xffffffffUL);
1562#endif
1563 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 if(errno) {
1565 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1566 return -1;
1567 }
1568 tcp->flags |= TCB_BPTSET;
1569
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001570#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001571#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001572 if (ia32) {
1573# define LOOP 0x0000feeb
1574 if (tcp->flags & TCB_BPTSET) {
1575 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1576 tcp->pid);
1577 return -1;
1578 }
1579 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1580 return -1;
1581 if (debug)
1582 fprintf(stderr, "[%d] setting bpt at %lx\n",
1583 tcp->pid, tcp->baddr);
1584 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1585 (char *) tcp->baddr, 0);
1586 if (errno) {
1587 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1588 return -1;
1589 }
1590 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1591 if (errno) {
1592 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1593 return -1;
1594 }
1595 tcp->flags |= TCB_BPTSET;
1596 } else {
1597 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001598 * Our strategy here is to replace the bundle that
1599 * contained the clone() syscall with a bundle of the
1600 * form:
1601 *
1602 * { 1: br 1b; br 1b; br 1b }
1603 *
1604 * This ensures that the newly forked child will loop
1605 * endlessly until we've got a chance to attach to it.
1606 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001607# define LOOP0 0x0000100000000017
1608# define LOOP1 0x4000000000200000
1609 unsigned long addr, ipsr;
1610 pid_t pid;
1611
1612 pid = tcp->pid;
1613 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1614 return -1;
1615 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1616 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001617 /* store "ri" in low two bits */
1618 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001619
1620 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001621 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1622 0);
1623 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1624 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001625 if (errno) {
1626 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1627 return -1;
1628 }
1629
1630 errno = 0;
1631 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1632 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1633 if (errno) {
1634 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1635 return -1;
1636 }
1637 tcp->flags |= TCB_BPTSET;
1638 }
1639#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640
Michal Ludvig0e035502002-09-23 15:41:01 +00001641#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642#define LOOP 0x0000feeb
1643#elif defined (M68K)
1644#define LOOP 0x60fe0000
1645#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001646#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001648#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001650#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001651#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001652#define LOOP 0x1000ffff
1653#elif defined(S390)
1654#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001655#elif defined(S390X)
1656#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001657#elif defined(HPPA)
1658#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001659#elif defined(SH)
1660#ifdef __LITTLE_ENDIAN__
1661#define LOOP 0x0000affe
1662#else
1663#define LOOP 0xfeaf0000
1664#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001665#else
1666#error unknown architecture
1667#endif
1668
1669 if (tcp->flags & TCB_BPTSET) {
1670 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1671 return -1;
1672 }
1673#if defined (I386)
1674 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1675 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001676#elif defined (X86_64)
1677 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1678 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001679#elif defined (M68K)
1680 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1681 return -1;
1682#elif defined (ALPHA)
1683 return -1;
1684#elif defined (ARM)
1685 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001686#elif defined (MIPS)
1687 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001689 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001690 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001691#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001692 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1693 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001694#elif defined(HPPA)
1695 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1696 return -1;
1697 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001698#elif defined(SH)
1699 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1700 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001701#else
1702#error unknown architecture
1703#endif
1704 if (debug)
1705 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1706 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1707 if (errno) {
1708 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1709 return -1;
1710 }
1711 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1712 if (errno) {
1713 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1714 return -1;
1715 }
1716 tcp->flags |= TCB_BPTSET;
1717
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001718#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001719#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720#endif /* LINUX */
1721
1722#ifdef SUNOS4
1723#ifdef SPARC /* This code is slightly sparc specific */
1724
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001725 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001726#define BPT 0x91d02001 /* ta 1 */
1727#define LOOP 0x10800000 /* ba 0 */
1728#define LOOPA 0x30800000 /* ba,a 0 */
1729#define NOP 0x01000000
1730#if LOOPA
1731 static int loopdeloop[1] = {LOOPA};
1732#else
1733 static int loopdeloop[2] = {LOOP, NOP};
1734#endif
1735
1736 if (tcp->flags & TCB_BPTSET) {
1737 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1738 return -1;
1739 }
1740 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1741 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1742 return -1;
1743 }
1744 tcp->baddr = regs.r_o7 + 8;
1745 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1746 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1747 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1748 return -1;
1749 }
1750
1751 /*
1752 * XXX - BRUTAL MODE ON
1753 * We cannot set a real BPT in the child, since it will not be
1754 * traced at the moment it will reach the trap and would probably
1755 * die with a core dump.
1756 * Thus, we are force our way in by taking out two instructions
1757 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1758 * generated by out PTRACE_ATTACH.
1759 * Of cause, if we evaporate ourselves in the middle of all this...
1760 */
1761 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1762 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1763 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1764 return -1;
1765 }
1766 tcp->flags |= TCB_BPTSET;
1767
1768#endif /* SPARC */
1769#endif /* SUNOS4 */
1770
1771 return 0;
1772}
1773
1774int
1775clearbpt(tcp)
1776struct tcb *tcp;
1777{
1778
1779#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001780#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001782#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001783 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001784#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001785 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001786#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001787 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001788#elif defined(HPPA)
1789 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001790#elif defined(SH)
1791 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001792#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001793
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001794#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001795 /* Again, we borrow the SunOS breakpoint code. */
1796 if (!(tcp->flags & TCB_BPTSET)) {
1797 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1798 return -1;
1799 }
1800 errno = 0;
1801 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1802 if(errno) {
1803 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1804 return -1;
1805 }
1806 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001807#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001808 if (ia32) {
1809 unsigned long addr;
1810
1811 if (debug)
1812 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1813 if (!(tcp->flags & TCB_BPTSET)) {
1814 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1815 return -1;
1816 }
1817 errno = 0;
1818 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1819 if (errno) {
1820 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1821 return -1;
1822 }
1823 tcp->flags &= ~TCB_BPTSET;
1824
1825 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1826 return -1;
1827 if (addr != tcp->baddr) {
1828 /* The breakpoint has not been reached yet. */
1829 if (debug)
1830 fprintf(stderr,
1831 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1832 addr, tcp->baddr);
1833 return 0;
1834 }
1835 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001836 unsigned long addr, ipsr;
1837 pid_t pid;
1838
1839 pid = tcp->pid;
1840
1841 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1842 return -1;
1843 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1844 return -1;
1845
1846 /* restore original bundle: */
1847 errno = 0;
1848 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1849 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1850 if (errno) {
1851 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1852 return -1;
1853 }
1854
1855 /* restore original "ri" in ipsr: */
1856 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1857 errno = 0;
1858 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1859 if (errno) {
1860 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1861 return -1;
1862 }
1863
1864 tcp->flags &= ~TCB_BPTSET;
1865
1866 if (addr != (tcp->baddr & ~0x3)) {
1867 /* the breakpoint has not been reached yet. */
1868 if (debug)
1869 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1870 addr, tcp->baddr);
1871 return 0;
1872 }
1873 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001874#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001875
1876 if (debug)
1877 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1878 if (!(tcp->flags & TCB_BPTSET)) {
1879 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1880 return -1;
1881 }
1882 errno = 0;
1883 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1884 if (errno) {
1885 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1886 return -1;
1887 }
1888 tcp->flags &= ~TCB_BPTSET;
1889
1890#ifdef I386
1891 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1892 return -1;
1893 if (eip != tcp->baddr) {
1894 /* The breakpoint has not been reached yet. */
1895 if (debug)
1896 fprintf(stderr,
1897 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1898 eip, tcp->baddr);
1899 return 0;
1900 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001901#elif defined(X86_64)
1902 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1903 return -1;
1904 if (eip != tcp->baddr) {
1905 /* The breakpoint has not been reached yet. */
1906 if (debug)
1907 fprintf(stderr,
1908 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1909 eip, tcp->baddr);
1910 return 0;
1911 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001912#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001913 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001914 return -1;
1915 if (pc != tcp->baddr) {
1916 /* The breakpoint has not been reached yet. */
1917 if (debug)
1918 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1919 pc, tcp->baddr);
1920 return 0;
1921 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001922#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001923 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1924 return -1;
1925 if (pc != tcp->baddr) {
1926 /* The breakpoint has not been reached yet. */
1927 if (debug)
1928 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1929 pc, tcp->baddr);
1930 return 0;
1931 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001932#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001933 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1934 return -1;
1935 if (pc != tcp->baddr) {
1936 /* The breakpoint has not been reached yet. */
1937 if (debug)
1938 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1939 pc, tcp->baddr);
1940 return 0;
1941 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001942#elif defined(HPPA)
1943 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1944 return -1;
1945 iaoq &= ~0x03;
1946 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1947 /* The breakpoint has not been reached yet. */
1948 if (debug)
1949 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1950 iaoq, tcp->baddr);
1951 return 0;
1952 }
1953 iaoq = tcp->baddr | 3;
1954 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1955 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1956 * has no significant effect.
1957 */
1958 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1959 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001960#elif defined(SH)
1961 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1962 return -1;
1963 if (pc != tcp->baddr) {
1964 /* The breakpoint has not been reached yet. */
1965 if (debug)
1966 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1967 pc, tcp->baddr);
1968 return 0;
1969 }
1970
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001971#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001972#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001973#endif /* LINUX */
1974
1975#ifdef SUNOS4
1976#ifdef SPARC
1977
1978#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001979 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001980#endif
1981
1982 if (!(tcp->flags & TCB_BPTSET)) {
1983 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1984 return -1;
1985 }
1986 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1987 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1988 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1989 return -1;
1990 }
1991 tcp->flags &= ~TCB_BPTSET;
1992
1993#if !LOOPA
1994 /*
1995 * Since we don't have a single instruction breakpoint, we may have
1996 * to adjust the program counter after removing the our `breakpoint'.
1997 */
1998 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1999 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2000 return -1;
2001 }
2002 if ((regs.r_pc < tcp->baddr) ||
2003 (regs.r_pc > tcp->baddr + 4)) {
2004 /* The breakpoint has not been reached yet */
2005 if (debug)
2006 fprintf(stderr,
2007 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2008 regs.r_pc, tcp->parent->baddr);
2009 return 0;
2010 }
2011 if (regs.r_pc != tcp->baddr)
2012 if (debug)
2013 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2014 regs.r_pc, tcp->baddr);
2015
2016 regs.r_pc = tcp->baddr;
2017 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2018 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2019 return -1;
2020 }
2021#endif /* LOOPA */
2022#endif /* SPARC */
2023#endif /* SUNOS4 */
2024
2025 return 0;
2026}
2027
Roland McGrathd81f1d92003-01-09 06:53:34 +00002028#endif
2029
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002030#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031
2032#ifdef SUNOS4
2033
2034static int
2035getex(pid, hdr)
2036int pid;
2037struct exec *hdr;
2038{
2039 int n;
2040
2041 for (n = 0; n < sizeof *hdr; n += 4) {
2042 long res;
2043 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
2044 return -1;
2045 memcpy(((char *) hdr) + n, &res, 4);
2046 }
2047 if (debug) {
2048 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2049 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2050 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2051 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2052 }
2053 return 0;
2054}
2055
2056int
2057fixvfork(tcp)
2058struct tcb *tcp;
2059{
2060 int pid = tcp->pid;
2061 /*
2062 * Change `vfork' in a freshly exec'ed dynamically linked
2063 * executable's (internal) symbol table to plain old `fork'
2064 */
2065
2066 struct exec hdr;
2067 struct link_dynamic dyn;
2068 struct link_dynamic_2 ld;
2069 char *strtab, *cp;
2070
2071 if (getex(pid, &hdr) < 0)
2072 return -1;
2073 if (!hdr.a_dynamic)
2074 return -1;
2075
2076 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2077 fprintf(stderr, "Cannot read DYNAMIC\n");
2078 return -1;
2079 }
2080 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2081 fprintf(stderr, "Cannot read link_dynamic_2\n");
2082 return -1;
2083 }
2084 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
Roland McGrath46100d02005-06-01 18:55:42 +00002085 fprintf(stderr, "out of memory\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002086 return -1;
2087 }
2088 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2089 (int)ld.ld_symb_size, strtab) < 0)
2090 goto err;
2091
2092#if 0
2093 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2094 fprintf(stderr, "[symbol: %s]\n", cp);
2095 cp += strlen(cp)+1;
2096 }
2097 return 0;
2098#endif
2099 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2100 if (strcmp(cp, "_vfork") == 0) {
2101 if (debug)
2102 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2103 strcpy(cp, "_fork");
2104 break;
2105 }
2106 cp += strlen(cp)+1;
2107 }
2108 if (cp < strtab + ld.ld_symb_size)
2109 /*
2110 * Write entire symbol table back to avoid
2111 * memory alignment bugs in ptrace
2112 */
2113 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2114 (int)ld.ld_symb_size, strtab) < 0)
2115 goto err;
2116
2117 free(strtab);
2118 return 0;
2119
2120err:
2121 free(strtab);
2122 return -1;
2123}
2124
2125#endif /* SUNOS4 */