blob: d445b0c4d8e1ffd31f2151fb15a811a189cbd775 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046#ifdef SUNOS4
47#include <machine/reg.h>
48#include <a.out.h>
49#include <link.h>
50#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000051
Wichert Akkerman43a74822000-06-27 17:33:32 +000052#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Wichert Akkerman36915a11999-07-13 15:45:02 +000053#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000054#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000055
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000056#if defined(LINUX) && defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000057# include <asm/ptrace_offsets.h>
58# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000059#endif
60
Wichert Akkerman36915a11999-07-13 15:45:02 +000061#ifdef HAVE_SYS_REG_H
62#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000066# ifdef HAVE_STRUCT_IA64_FPREG
67# define ia64_fpreg XXX_ia64_fpreg
68# endif
69# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70# define pt_all_user_regs XXX_pt_all_user_regs
71# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000072#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000073# undef ia64_fpreg
74# undef pt_all_user_regs
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000075#endif
76
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78#include <sys/utsname.h>
79#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
Roland McGrath6d1a65c2004-07-12 07:44:08 +000081#if defined(LINUXSPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
Roland McGrath4db26242003-01-30 20:15:19 +000083# define fpq kernel_fpq
84# define fq kernel_fq
85# define fpu kernel_fpu
86# include <asm/reg.h>
87# undef fpq
88# undef fq
89# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000090
Roland McGrath6d1a65c2004-07-12 07:44:08 +000091#if defined (SPARC64)
92# define r_pc r_tpc
93# undef PTRACE_GETREGS
94# define PTRACE_GETREGS PTRACE_GETREGS64
95# undef PTRACE_SETREGS
96# define PTRACE_SETREGS PTRACE_SETREGS64
97#endif /* SPARC64 */
98
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000099#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100
101#include <linux/unistd.h>
102
103#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
104 type5,arg5,syscall) \
105type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
106{ \
107 long __res; \
108\
109__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
110 "or %%g0, %2, %%o1\n\t" \
111 "or %%g0, %3, %%o2\n\t" \
112 "or %%g0, %4, %%o3\n\t" \
113 "or %%g0, %5, %%o4\n\t" \
114 "or %%g0, %6, %%g1\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000115#if defined (SPARC64)
116 "t 0x6d\n\t" \
117#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118 "t 0x10\n\t" \
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000119#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120 "bcc 1f\n\t" \
121 "or %%g0, %%o0, %0\n\t" \
122 "sub %%g0, %%o0, %0\n\t" \
123 "1:\n\t" \
124 : "=r" (__res) \
125 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
126 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
127 "i" (__NR_##syscall) \
128 : "g1", "o0", "o1", "o2", "o3", "o4"); \
129if (__res>=0) \
130 return (type) __res; \
131errno = -__res; \
132return -1; \
133}
134
135static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
136
137#define _ptrace
138
139#endif
140
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000141#endif
142
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143/* macros */
144#ifndef MAX
145#define MAX(a,b) (((a) > (b)) ? (a) : (b))
146#endif
147#ifndef MIN
148#define MIN(a,b) (((a) < (b)) ? (a) : (b))
149#endif
150
151void
152tv_tv(tv, a, b)
153struct timeval *tv;
154int a;
155int b;
156{
157 tv->tv_sec = a;
158 tv->tv_usec = b;
159}
160
161int
162tv_nz(a)
163struct timeval *a;
164{
165 return a->tv_sec || a->tv_usec;
166}
167
168int
169tv_cmp(a, b)
170struct timeval *a, *b;
171{
172 if (a->tv_sec < b->tv_sec
173 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
174 return -1;
175 if (a->tv_sec > b->tv_sec
176 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
177 return 1;
178 return 0;
179}
180
181double
182tv_float(tv)
183struct timeval *tv;
184{
185 return tv->tv_sec + tv->tv_usec/1000000.0;
186}
187
188void
189tv_add(tv, a, b)
190struct timeval *tv, *a, *b;
191{
192 tv->tv_sec = a->tv_sec + b->tv_sec;
193 tv->tv_usec = a->tv_usec + b->tv_usec;
194 if (tv->tv_usec > 1000000) {
195 tv->tv_sec++;
196 tv->tv_usec -= 1000000;
197 }
198}
199
200void
201tv_sub(tv, a, b)
202struct timeval *tv, *a, *b;
203{
204 tv->tv_sec = a->tv_sec - b->tv_sec;
205 tv->tv_usec = a->tv_usec - b->tv_usec;
206 if (((long) tv->tv_usec) < 0) {
207 tv->tv_sec--;
208 tv->tv_usec += 1000000;
209 }
210}
211
212void
213tv_div(tv, a, n)
214struct timeval *tv, *a;
215int n;
216{
217 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
218 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
219 tv->tv_usec %= 1000000;
220}
221
222void
223tv_mul(tv, a, n)
224struct timeval *tv, *a;
225int n;
226{
227 tv->tv_usec = a->tv_usec * n;
228 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
229 tv->tv_usec %= 1000000;
230}
231
232char *
233xlookup(xlat, val)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000234const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235int val;
236{
237 for (; xlat->str != NULL; xlat++)
238 if (xlat->val == val)
239 return xlat->str;
240 return NULL;
241}
242
243/*
244 * Print entry in struct xlat table, if there.
245 */
246void
247printxval(xlat, val, dflt)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000248const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000249int val;
250char *dflt;
251{
252 char *str = xlookup(xlat, val);
253
254 if (str)
255 tprintf("%s", str);
256 else
257 tprintf("%#x /* %s */", val, dflt);
258}
259
260/*
261 * Interpret `xlat' as an array of flags
262 * print the entries whose bits are on in `flags'
263 * return # of flags printed.
264 */
265int
266addflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000267const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000268int flags;
269{
270 int n;
271
272 for (n = 0; xlat->str; xlat++) {
273 if (xlat->val && (flags & xlat->val) == xlat->val) {
274 tprintf("|%s", xlat->str);
275 flags &= ~xlat->val;
276 n++;
277 }
278 }
279 if (flags) {
280 tprintf("|%#x", flags);
281 n++;
282 }
283 return n;
284}
285
286int
287printflags(xlat, flags)
Roland McGrathd9f816f2004-09-04 03:39:20 +0000288const struct xlat *xlat;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000289int flags;
290{
291 int n;
292 char *sep;
293
294 if (flags == 0 && xlat->val == 0) {
295 tprintf("%s", xlat->str);
296 return 1;
297 }
298
299 sep = "";
300 for (n = 0; xlat->str; xlat++) {
301 if (xlat->val && (flags & xlat->val) == xlat->val) {
302 tprintf("%s%s", sep, xlat->str);
303 flags &= ~xlat->val;
304 sep = "|";
305 n++;
306 }
307 }
308 if (flags) {
309 tprintf("%s%#x", sep, flags);
310 n++;
311 }
312 return n;
313}
314
315void
316printnum(tcp, addr, fmt)
317struct tcb *tcp;
318long addr;
319char *fmt;
320{
Roland McGratheb285352003-01-14 09:59:00 +0000321 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000322
323 if (!addr) {
324 tprintf("NULL");
325 return;
326 }
327 if (umove(tcp, addr, &num) < 0) {
328 tprintf("%#lx", addr);
329 return;
330 }
331 tprintf("[");
332 tprintf(fmt, num);
333 tprintf("]");
334}
335
Roland McGrath6bc12202003-11-13 22:32:27 +0000336void
337printuid(text, uid)
338const char *text;
339unsigned long uid;
340{
341 tprintf("%s", text);
342 tprintf((uid == -1) ? "%ld" : "%lu", uid);
343}
344
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000345static char path[MAXPATHLEN + 1];
346
347void
348string_quote(str)
349char *str;
350{
351 char buf[2 * MAXPATHLEN + 1];
352 char *s;
353
354 if (!strpbrk(str, "\"\'\\")) {
355 tprintf("\"%s\"", str);
356 return;
357 }
358 for (s = buf; *str; str++) {
359 switch (*str) {
360 case '\"': case '\'': case '\\':
361 *s++ = '\\'; *s++ = *str; break;
362 default:
363 *s++ = *str; break;
364 }
365 }
366 *s = '\0';
367 tprintf("\"%s\"", buf);
368}
369
370void
371printpath(tcp, addr)
372struct tcb *tcp;
373long addr;
374{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000375 if (addr == 0)
376 tprintf("NULL");
377 else if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000378 tprintf("%#lx", addr);
379 else
380 string_quote(path);
381 return;
382}
383
384void
385printpathn(tcp, addr, n)
386struct tcb *tcp;
387long addr;
388int n;
389{
Roland McGrath371ed8f2005-02-06 01:55:07 +0000390 if (addr == 0)
391 tprintf("NULL");
392 else if (umovestr(tcp, addr, n, path) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000393 tprintf("%#lx", addr);
394 else {
395 path[n] = '\0';
396 string_quote(path);
397 }
398}
399
400void
401printstr(tcp, addr, len)
402struct tcb *tcp;
403long addr;
404int len;
405{
406 static unsigned char *str = NULL;
407 static char *outstr;
408 int i, n, c, usehex;
409 char *s, *outend;
410
411 if (!addr) {
412 tprintf("NULL");
413 return;
414 }
415 if (!str) {
416 if ((str = malloc(max_strlen)) == NULL
417 || (outstr = malloc(2*max_strlen)) == NULL) {
418 fprintf(stderr, "printstr: no memory\n");
419 tprintf("%#lx", addr);
420 return;
421 }
422 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000423 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000424 if (len < 0) {
425 n = max_strlen;
426 if (umovestr(tcp, addr, n, (char *) str) < 0) {
427 tprintf("%#lx", addr);
428 return;
429 }
430 }
431 else {
432 n = MIN(len, max_strlen);
433 if (umoven(tcp, addr, n, (char *) str) < 0) {
434 tprintf("%#lx", addr);
435 return;
436 }
437 }
438
439 usehex = 0;
440 if (xflag > 1)
441 usehex = 1;
442 else if (xflag) {
443 for (i = 0; i < n; i++) {
444 c = str[i];
445 if (len < 0 && c == '\0')
446 break;
447 if (!isprint(c) && !isspace(c)) {
448 usehex = 1;
449 break;
450 }
451 }
452 }
453
454 s = outstr;
455 *s++ = '\"';
456
457 if (usehex) {
458 for (i = 0; i < n; i++) {
459 c = str[i];
460 if (len < 0 && c == '\0')
461 break;
462 sprintf(s, "\\x%02x", c);
463 s += 4;
464 if (s > outend)
465 break;
466 }
467 }
468 else {
469 for (i = 0; i < n; i++) {
470 c = str[i];
471 if (len < 0 && c == '\0')
472 break;
473 switch (c) {
474 case '\"': case '\'': case '\\':
475 *s++ = '\\'; *s++ = c; break;
476 case '\f':
477 *s++ = '\\'; *s++ = 'f'; break;
478 case '\n':
479 *s++ = '\\'; *s++ = 'n'; break;
480 case '\r':
481 *s++ = '\\'; *s++ = 'r'; break;
482 case '\t':
483 *s++ = '\\'; *s++ = 't'; break;
484 case '\v':
485 *s++ = '\\'; *s++ = 'v'; break;
486 default:
487 if (isprint(c))
488 *s++ = c;
489 else if (i < n - 1 && isdigit(str[i + 1])) {
490 sprintf(s, "\\%03o", c);
491 s += 4;
492 }
493 else {
494 sprintf(s, "\\%o", c);
495 s += strlen(s);
496 }
497 break;
498 }
499 if (s > outend)
500 break;
501 }
502 }
503
504 *s++ = '\"';
505 if (i < len || (len < 0 && (i == n || s > outend))) {
506 *s++ = '.'; *s++ = '.'; *s++ = '.';
507 }
508 *s = '\0';
509 tprintf("%s", outstr);
510}
511
John Hughes1d08dcf2001-07-10 13:48:44 +0000512#if HAVE_SYS_UIO_H
513void
514dumpiov(tcp, len, addr)
515struct tcb * tcp;
516int len;
517long addr;
518{
519 struct iovec *iov;
520 int i;
521
Roland McGrath1e85cf92002-12-16 20:40:54 +0000522
John Hughes1d08dcf2001-07-10 13:48:44 +0000523 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
524 fprintf(stderr, "dump: No memory");
525 return;
526 }
527 if (umoven(tcp, addr,
528 len * sizeof *iov, (char *) iov) >= 0) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000529
John Hughes1d08dcf2001-07-10 13:48:44 +0000530 for (i = 0; i < len; i++) {
531 /* include the buffer number to make it easy to
532 * match up the trace with the source */
533 tprintf(" * %lu bytes in buffer %d\n",
534 (unsigned long)iov[i].iov_len, i);
535 dumpstr(tcp, (long) iov[i].iov_base,
536 iov[i].iov_len);
537 }
538 }
539 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000540
John Hughes1d08dcf2001-07-10 13:48:44 +0000541}
542#endif
543
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000544void
545dumpstr(tcp, addr, len)
546struct tcb *tcp;
547long addr;
548int len;
549{
550 static int strsize = -1;
551 static unsigned char *str;
552 static char outstr[80];
553 char *s;
554 int i, j;
555
556 if (strsize < len) {
557 if (str)
558 free(str);
559 if ((str = malloc(len)) == NULL) {
560 fprintf(stderr, "dump: no memory\n");
561 return;
562 }
563 strsize = len;
564 }
565
566 if (umoven(tcp, addr, len, (char *) str) < 0)
567 return;
568
569 for (i = 0; i < len; i += 16) {
570 s = outstr;
571 sprintf(s, " | %05x ", i);
572 s += 9;
573 for (j = 0; j < 16; j++) {
574 if (j == 8)
575 *s++ = ' ';
576 if (i + j < len) {
577 sprintf(s, " %02x", str[i + j]);
578 s += 3;
579 }
580 else {
581 *s++ = ' '; *s++ = ' '; *s++ = ' ';
582 }
583 }
584 *s++ = ' '; *s++ = ' ';
585 for (j = 0; j < 16; j++) {
586 if (j == 8)
587 *s++ = ' ';
588 if (i + j < len) {
589 if (isprint(str[i + j]))
590 *s++ = str[i + j];
591 else
592 *s++ = '.';
593 }
594 else
595 *s++ = ' ';
596 }
597 tprintf("%s |\n", outstr);
598 }
599}
600
601#define PAGMASK (~(PAGSIZ - 1))
602/*
603 * move `len' bytes of data from process `pid'
604 * at address `addr' to our space at `laddr'
605 */
606int
607umoven(tcp, addr, len, laddr)
608struct tcb *tcp;
609long addr;
610int len;
611char *laddr;
612{
613
614#ifdef LINUX
615 int pid = tcp->pid;
616 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000617 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000618 union {
619 long val;
620 char x[sizeof(long)];
621 } u;
622
623 if (addr & (sizeof(long) - 1)) {
624 /* addr not a multiple of sizeof(long) */
625 n = addr - (addr & -sizeof(long)); /* residue */
626 addr &= -sizeof(long); /* residue */
627 errno = 0;
628 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
629 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000630 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631 /* Ran into 'end of memory' - stupid "printpath" */
632 return 0;
633 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000634 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000635 perror("ptrace: umoven");
636 return -1;
637 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000638 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000639 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
640 addr += sizeof(long), laddr += m, len -= m;
641 }
642 while (len) {
643 errno = 0;
644 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
645 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000646 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000647 /* Ran into 'end of memory' - stupid "printpath" */
648 return 0;
649 }
Roland McGrath4db26242003-01-30 20:15:19 +0000650 if (addr != 0)
651 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000652 return -1;
653 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000654 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
656 addr += sizeof(long), laddr += m, len -= m;
657 }
658#endif /* LINUX */
659
660#ifdef SUNOS4
661 int pid = tcp->pid;
662#if 0
663 int n, m;
664 union {
665 long val;
666 char x[sizeof(long)];
667 } u;
668
669 if (addr & (sizeof(long) - 1)) {
670 /* addr not a multiple of sizeof(long) */
671 n = addr - (addr & -sizeof(long)); /* residue */
672 addr &= -sizeof(long); /* residue */
673 errno = 0;
674 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
675 if (errno) {
676 perror("umoven");
677 return -1;
678 }
679 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
680 addr += sizeof(long), laddr += m, len -= m;
681 }
682 while (len) {
683 errno = 0;
684 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
685 if (errno) {
686 perror("umoven");
687 return -1;
688 }
689 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
690 addr += sizeof(long), laddr += m, len -= m;
691 }
692#else /* !oldway */
693 int n;
694
695 while (len) {
696 n = MIN(len, PAGSIZ);
697 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
698 if (ptrace(PTRACE_READDATA, pid,
699 (char *) addr, len, laddr) < 0) {
700 perror("umoven: ptrace(PTRACE_READDATA, ...)");
701 abort();
702 return -1;
703 }
704 len -= n;
705 addr += n;
706 laddr += n;
707 }
708#endif /* !oldway */
709#endif /* SUNOS4 */
710
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000711#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000712#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000713 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000714#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000715 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000716#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000717 lseek(fd, addr, SEEK_SET);
718 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000720#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000721
722 return 0;
723}
724
725/*
726 * like `umove' but make the additional effort of looking
727 * for a terminating zero byte.
728 */
729int
730umovestr(tcp, addr, len, laddr)
731struct tcb *tcp;
732long addr;
733int len;
734char *laddr;
735{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000736#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000737#ifdef HAVE_MP_PROCFS
738 int fd = tcp->pfd_as;
739#else
740 int fd = tcp->pfd;
741#endif
742 /* Some systems (e.g. FreeBSD) can be upset if we read off the
743 end of valid memory, avoid this by trying to read up
744 to page boundaries. But we don't know what a page is (and
745 getpagesize(2) (if it exists) doesn't necessarily return
746 hardware page size). Assume all pages >= 1024 (a-historical
747 I know) */
748
749 int page = 1024; /* How to find this? */
750 int move = page - (addr & (page - 1));
751 int left = len;
752
753 lseek(fd, addr, SEEK_SET);
754
755 while (left) {
756 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000757 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000758 return left != len ? 0 : -1;
759 if (memchr (laddr, 0, move)) break;
760 left -= move;
761 laddr += move;
762 addr += move;
763 move = page;
764 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000765#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000766 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 int pid = tcp->pid;
768 int i, n, m;
769 union {
770 long val;
771 char x[sizeof(long)];
772 } u;
773
774 if (addr & (sizeof(long) - 1)) {
775 /* addr not a multiple of sizeof(long) */
776 n = addr - (addr & -sizeof(long)); /* residue */
777 addr &= -sizeof(long); /* residue */
778 errno = 0;
779 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
780 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000781 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000782 /* Ran into 'end of memory' - stupid "printpath" */
783 return 0;
784 }
785 perror("umovestr");
786 return -1;
787 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000788 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000789 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
790 while (n & (sizeof(long) - 1))
791 if (u.x[n++] == '\0')
792 return 0;
793 addr += sizeof(long), laddr += m, len -= m;
794 }
795 while (len) {
796 errno = 0;
797 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
798 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000799 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000800 /* Ran into 'end of memory' - stupid "printpath" */
801 return 0;
802 }
803 perror("umovestr");
804 return -1;
805 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000806 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000807 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
808 for (i = 0; i < sizeof(long); i++)
809 if (u.x[i] == '\0')
810 return 0;
811
812 addr += sizeof(long), laddr += m, len -= m;
813 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000814#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000815 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000816}
817
818#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000819#if !defined (SPARC) && !defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000820#define PTRACE_WRITETEXT 101
821#define PTRACE_WRITEDATA 102
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000822#endif /* !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000823#endif /* LINUX */
824
825#ifdef SUNOS4
826
827static int
828uload(cmd, pid, addr, len, laddr)
829int cmd;
830int pid;
831long addr;
832int len;
833char *laddr;
834{
835#if 0
836 int n;
837
838 while (len) {
839 n = MIN(len, PAGSIZ);
840 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
841 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
842 perror("uload: ptrace(PTRACE_WRITE, ...)");
843 return -1;
844 }
845 len -= n;
846 addr += n;
847 laddr += n;
848 }
849#else
850 int peek, poke;
851 int n, m;
852 union {
853 long val;
854 char x[sizeof(long)];
855 } u;
856
857 if (cmd == PTRACE_WRITETEXT) {
858 peek = PTRACE_PEEKTEXT;
859 poke = PTRACE_POKETEXT;
860 }
861 else {
862 peek = PTRACE_PEEKDATA;
863 poke = PTRACE_POKEDATA;
864 }
865 if (addr & (sizeof(long) - 1)) {
866 /* addr not a multiple of sizeof(long) */
867 n = addr - (addr & -sizeof(long)); /* residue */
868 addr &= -sizeof(long);
869 errno = 0;
870 u.val = ptrace(peek, pid, (char *) addr, 0);
871 if (errno) {
872 perror("uload: POKE");
873 return -1;
874 }
875 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
876 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
877 perror("uload: POKE");
878 return -1;
879 }
880 addr += sizeof(long), laddr += m, len -= m;
881 }
882 while (len) {
883 if (len < sizeof(long))
884 u.val = ptrace(peek, pid, (char *) addr, 0);
885 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
886 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
887 perror("uload: POKE");
888 return -1;
889 }
890 addr += sizeof(long), laddr += m, len -= m;
891 }
892#endif
893 return 0;
894}
895
896int
897tload(pid, addr, len, laddr)
898int pid;
899int addr, len;
900char *laddr;
901{
902 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
903}
904
905int
906dload(pid, addr, len, laddr)
907int pid;
908int addr;
909int len;
910char *laddr;
911{
912 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
913}
914
915#endif /* SUNOS4 */
916
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000917#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000918
919int
920upeek(pid, off, res)
921int pid;
922long off;
923long *res;
924{
925 long val;
926
927#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
928 {
929 static int is_sun4m = -1;
930 struct utsname name;
931
932 /* Round up the usual suspects. */
933 if (is_sun4m == -1) {
934 if (uname(&name) < 0) {
935 perror("upeek: uname?");
936 exit(1);
937 }
938 is_sun4m = strcmp(name.machine, "sun4m") == 0;
939 if (is_sun4m) {
Roland McGrathd9f816f2004-09-04 03:39:20 +0000940 extern const struct xlat struct_user_offsets[];
941 const struct xlat *x;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942
943 for (x = struct_user_offsets; x->str; x++)
944 x->val += 1024;
945 }
946 }
947 if (is_sun4m)
948 off += 1024;
949 }
950#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
951 errno = 0;
952 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
953 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000954 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000955 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000956 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 return -1;
958 }
959 *res = val;
960 return 0;
961}
962
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000963#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000964
965long
966getpc(tcp)
967struct tcb *tcp;
968{
969
970#ifdef LINUX
971 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000972#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
974 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000975#elif defined(X86_64)
976 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
977 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000978#elif defined(IA64)
979 if (upeek(tcp->pid, PT_B0, &pc) < 0)
980 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000981#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000982 if (upeek(tcp->pid, 4*15, &pc) < 0)
983 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000984#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000985 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000986 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000987#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
989 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000990#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 if (upeek(tcp->pid, REG_PC, &pc) < 0)
992 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000993#elif defined(MIPS)
994 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
995 return -1;
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000996#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000997 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
999 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001000 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001001#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001002 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +00001003 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001004#elif defined(HPPA)
1005 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
1006 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001007#elif defined(SH)
1008 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
1009 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001010#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001011 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
1012 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +00001013#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 return pc;
1015#endif /* LINUX */
1016
1017#ifdef SUNOS4
1018 /*
1019 * Return current program counter for `pid'
1020 * Assumes PC is never 0xffffffff
1021 */
1022 struct regs regs;
1023
1024 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1025 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1026 return -1;
1027 }
1028 return regs.r_pc;
1029#endif /* SUNOS4 */
1030
1031#ifdef SVR4
1032 /* XXX */
1033 return 0;
1034#endif /* SVR4 */
1035
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001036#ifdef FREEBSD
1037 struct reg regs;
1038 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1039 return regs.r_eip;
1040#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041}
1042
1043void
1044printcall(tcp)
1045struct tcb *tcp;
1046{
Roland McGrath7a918832005-02-02 20:55:23 +00001047#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1048 sizeof(long) == 8 ? "[????????????????] " : \
1049 NULL /* crash */)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050
1051#ifdef LINUX
1052#ifdef I386
1053 long eip;
1054
1055 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001056 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001057 return;
1058 }
1059 tprintf("[%08lx] ", eip);
Roland McGratheac26fc2005-02-02 02:48:53 +00001060
1061#elif defined(S390) || defined(S390X)
1062 long psw;
1063 if(upeek(tcp->pid,PT_PSWADDR,&psw) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001064 PRINTBADPC;
Roland McGratheac26fc2005-02-02 02:48:53 +00001065 return;
1066 }
1067#ifdef S390
1068 tprintf("[%08lx] ", psw);
1069#elif S390X
1070 tprintf("[%16lx] ", psw);
1071#endif
1072
Michal Ludvig0e035502002-09-23 15:41:01 +00001073#elif defined(X86_64)
1074 long rip;
1075
1076 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001077 PRINTBADPC;
Michal Ludvig0e035502002-09-23 15:41:01 +00001078 return;
1079 }
1080 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001081#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001082 long ip;
1083
1084 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001085 PRINTBADPC;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001086 return;
1087 }
1088 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001089#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001090 long pc;
1091
Roland McGratheb285352003-01-14 09:59:00 +00001092 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093 tprintf ("[????????] ");
1094 return;
1095 }
1096 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001097#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001098 long pc;
1099
1100 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1101 tprintf ("[????????] ");
1102 return;
1103 }
1104 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001105#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106 long pc;
1107
1108 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001109 tprintf ("[????????????????] ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001110 return;
1111 }
1112 tprintf("[%08lx] ", pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001113#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001114 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001115 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001116 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 return;
1118 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001119 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001120#elif defined(HPPA)
1121 long pc;
1122
1123 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1124 tprintf ("[????????] ");
1125 return;
1126 }
1127 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001128#elif defined(MIPS)
1129 long pc;
1130
1131 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1132 tprintf ("[????????] ");
1133 return;
1134 }
1135 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001136#elif defined(SH)
1137 long pc;
1138
1139 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1140 tprintf ("[????????] ");
1141 return;
1142 }
1143 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001144#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001145 long pc;
1146
1147 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001148 tprintf ("[????????????????] ");
Roland McGrathe1e584b2003-06-02 19:18:58 +00001149 return;
1150 }
1151 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001152#elif defined(ARM)
1153 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001154
Roland McGrathef388682003-06-03 23:28:59 +00001155 if (upeek(tcp->pid, 4*15, &pc) < 0) {
Roland McGrath7a918832005-02-02 20:55:23 +00001156 PRINTBADPC;
Roland McGrathef388682003-06-03 23:28:59 +00001157 return;
1158 }
1159 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001160#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161#endif /* LINUX */
1162
1163#ifdef SUNOS4
1164 struct regs regs;
1165
1166 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1167 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
Roland McGrath7a918832005-02-02 20:55:23 +00001168 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 return;
1170 }
1171 tprintf("[%08x] ", regs.r_o7);
1172#endif /* SUNOS4 */
1173
1174#ifdef SVR4
1175 /* XXX */
Roland McGrath7a918832005-02-02 20:55:23 +00001176 PRINTBADPC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177#endif
1178
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001179#ifdef FREEBSD
1180 struct reg regs;
1181 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1182 tprintf("[%08x] ", regs.r_eip);
1183#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184}
1185
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001186#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187
Roland McGrathd81f1d92003-01-09 06:53:34 +00001188#if defined LINUX
1189
1190#include <sys/syscall.h>
1191#ifndef CLONE_PTRACE
1192# define CLONE_PTRACE 0x00002000
1193#endif
1194
1195#ifdef IA64
1196
Roland McGrath08267b82004-02-20 22:56:43 +00001197/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1198 subsystem has them for x86... */
1199#define SYS_fork 2
1200#define SYS_vfork 190
1201
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202typedef unsigned long *arg_setup_state;
1203
1204static int
1205arg_setup(struct tcb *tcp, arg_setup_state *state)
1206{
1207 unsigned long *bsp, cfm, sof, sol;
1208
Roland McGrath08267b82004-02-20 22:56:43 +00001209 if (ia32)
1210 return 0;
1211
Roland McGrathd81f1d92003-01-09 06:53:34 +00001212 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1213 return -1;
1214 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1215 return -1;
1216
1217 sof = (cfm >> 0) & 0x7f;
1218 sol = (cfm >> 7) & 0x7f;
1219 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1220
1221 *state = bsp;
1222 return 0;
1223}
1224
1225# define arg_finish_change(tcp, state) 0
1226
1227#ifdef SYS_fork
1228static int
1229get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1230{
Roland McGrath08267b82004-02-20 22:56:43 +00001231 int ret;
1232
1233 if (ia32)
1234 ret = upeek (tcp->pid, PT_R11, valp);
1235 else
1236 ret = umoven (tcp,
1237 (unsigned long) ia64_rse_skip_regs(*state, 0),
1238 sizeof(long), (void *) valp);
1239 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001240}
1241
1242static int
1243get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1244{
Roland McGrath08267b82004-02-20 22:56:43 +00001245 int ret;
1246
1247 if (ia32)
1248 ret = upeek (tcp->pid, PT_R9, valp);
1249 else
1250 ret = umoven (tcp,
1251 (unsigned long) ia64_rse_skip_regs(*state, 1),
1252 sizeof(long), (void *) valp);
1253 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001254}
1255#endif
1256
1257static int
1258set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1259{
Roland McGrath08267b82004-02-20 22:56:43 +00001260 int req = PTRACE_POKEDATA;
1261 void *ap;
1262
1263 if (ia32) {
1264 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1265 req = PTRACE_POKEUSER;
1266 } else
1267 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001268 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001269 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001270 return errno ? -1 : 0;
1271}
1272
1273static int
1274set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1275{
Roland McGrath08267b82004-02-20 22:56:43 +00001276 int req = PTRACE_POKEDATA;
1277 void *ap;
1278
1279 if (ia32) {
1280 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1281 req = PTRACE_POKEUSER;
1282 } else
1283 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001285 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001286 return errno ? -1 : 0;
1287}
1288
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001289#elif defined (SPARC) || defined (SPARC64)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001290
1291typedef struct regs arg_setup_state;
1292
1293# define arg_setup(tcp, state) \
1294 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1295# define arg_finish_change(tcp, state) \
1296 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1297
1298# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1299# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1300# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1301# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001302# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001303
1304#else
1305
1306# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001307/* Note: this is only true for the `clone' system call, which handles
1308 arguments specially. We could as well say that its first two arguments
1309 are swapped relative to other architectures, but that would just be
1310 another #ifdef in the calls. */
1311# define arg0_offset PT_GPR3
1312# define arg1_offset PT_ORIGGPR2
1313# define restore_arg0(tcp, state, val) ((void) (state), 0)
1314# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001315# define arg0_index 1
1316# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001317# elif defined (ALPHA) || defined (MIPS)
1318# define arg0_offset REG_A0
1319# define arg1_offset (REG_A0+1)
1320# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001321# define arg0_offset (sizeof(unsigned long)*PT_R3)
1322# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001323# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001324# elif defined (HPPA)
1325# define arg0_offset PT_GR26
1326# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001327# elif defined (X86_64)
1328# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1329# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001330# elif defined (SH)
1331# define arg0_offset (4*(REG_REG0+4))
1332# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001333# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001334 /* ABI defines arg0 & 1 in r2 & r3 */
1335# define arg0_offset (REG_OFFSET+16)
1336# define arg1_offset (REG_OFFSET+24)
1337# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001338# else
1339# define arg0_offset 0
1340# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001341# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001342# define restore_arg0(tcp, state, val) 0
1343# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001344# endif
1345
1346typedef int arg_setup_state;
1347
1348# define arg_setup(tcp, state) (0)
1349# define arg_finish_change(tcp, state) 0
1350# define get_arg0(tcp, cookie, valp) \
1351 (upeek ((tcp)->pid, arg0_offset, (valp)))
1352# define get_arg1(tcp, cookie, valp) \
1353 (upeek ((tcp)->pid, arg1_offset, (valp)))
1354
1355static int
1356set_arg0 (struct tcb *tcp, void *cookie, long val)
1357{
1358 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1359}
1360
1361static int
1362set_arg1 (struct tcb *tcp, void *cookie, long val)
1363{
1364 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1365}
1366
1367#endif
1368
Roland McGrathe1df47f2003-01-14 09:46:15 +00001369#ifndef restore_arg0
1370# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1371#endif
1372#ifndef restore_arg1
1373# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1374#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001375
Roland McGrath90d0afd2004-03-01 21:05:16 +00001376#ifndef arg0_index
1377# define arg0_index 0
1378# define arg1_index 1
1379#endif
1380
Roland McGrathd81f1d92003-01-09 06:53:34 +00001381int
1382setbpt(tcp)
1383struct tcb *tcp;
1384{
1385 extern int change_syscall(struct tcb *, int);
1386 arg_setup_state state;
1387
1388 if (tcp->flags & TCB_BPTSET) {
1389 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1390 return -1;
1391 }
1392
1393 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001394#ifdef SYS_vfork
1395 case SYS_vfork:
1396#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001397#ifdef SYS_fork
1398 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001399#endif
1400#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001401 if (arg_setup (tcp, &state) < 0
1402 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1403 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1404 || change_syscall(tcp, SYS_clone) < 0
1405 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1406 || set_arg1 (tcp, &state, 0) < 0
1407 || arg_finish_change (tcp, &state) < 0)
1408 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001409 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1410 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001411 tcp->flags |= TCB_BPTSET;
1412 return 0;
1413#endif
1414
1415 case SYS_clone:
1416#ifdef SYS_clone2
1417 case SYS_clone2:
1418#endif
Roland McGrath02cee8d2004-03-02 08:50:42 +00001419 if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001420 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001421 || set_arg0 (tcp, &state,
1422 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001423 || arg_finish_change (tcp, &state) < 0))
1424 return -1;
1425 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001426 tcp->inst[0] = tcp->u_arg[arg0_index];
1427 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001428 return 0;
1429
1430 default:
1431 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1432 tcp->scno, tcp->pid);
1433 break;
1434 }
1435
1436 return -1;
1437}
1438
1439int
1440clearbpt(tcp)
1441struct tcb *tcp;
1442{
1443 arg_setup_state state;
1444 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001445 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1446 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001447 || arg_finish_change (tcp, &state))
1448 return -1;
1449 tcp->flags &= ~TCB_BPTSET;
1450 return 0;
1451}
1452
1453#else
1454
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455int
1456setbpt(tcp)
1457struct tcb *tcp;
1458{
1459
1460#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001461#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462 /* We simply use the SunOS breakpoint code. */
1463
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001464 struct regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001465 unsigned long inst;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001466#define LOOPA 0x30800000 /* ba,a 0 */
1467
1468 if (tcp->flags & TCB_BPTSET) {
1469 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1470 return -1;
1471 }
1472 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1473 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1474 return -1;
1475 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001476 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477 errno = 0;
1478 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1479 if(errno) {
1480 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1481 return -1;
1482 }
1483
1484 /*
1485 * XXX - BRUTAL MODE ON
1486 * We cannot set a real BPT in the child, since it will not be
1487 * traced at the moment it will reach the trap and would probably
1488 * die with a core dump.
1489 * Thus, we are force our way in by taking out two instructions
1490 * and insert an eternal loop instead, in expectance of the SIGSTOP
1491 * generated by out PTRACE_ATTACH.
1492 * Of cause, if we evaporate ourselves in the middle of all this...
1493 */
1494 errno = 0;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001495 inst = LOOPA;
1496#if defined (SPARC64)
1497 inst <<= 32;
1498 inst |= (tcp->inst[0] & 0xffffffffUL);
1499#endif
1500 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501 if(errno) {
1502 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1503 return -1;
1504 }
1505 tcp->flags |= TCB_BPTSET;
1506
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001507#else /* !SPARC && !SPARC64 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001508#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001509 if (ia32) {
1510# define LOOP 0x0000feeb
1511 if (tcp->flags & TCB_BPTSET) {
1512 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1513 tcp->pid);
1514 return -1;
1515 }
1516 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1517 return -1;
1518 if (debug)
1519 fprintf(stderr, "[%d] setting bpt at %lx\n",
1520 tcp->pid, tcp->baddr);
1521 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1522 (char *) tcp->baddr, 0);
1523 if (errno) {
1524 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1525 return -1;
1526 }
1527 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1528 if (errno) {
1529 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1530 return -1;
1531 }
1532 tcp->flags |= TCB_BPTSET;
1533 } else {
1534 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001535 * Our strategy here is to replace the bundle that
1536 * contained the clone() syscall with a bundle of the
1537 * form:
1538 *
1539 * { 1: br 1b; br 1b; br 1b }
1540 *
1541 * This ensures that the newly forked child will loop
1542 * endlessly until we've got a chance to attach to it.
1543 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001544# define LOOP0 0x0000100000000017
1545# define LOOP1 0x4000000000200000
1546 unsigned long addr, ipsr;
1547 pid_t pid;
1548
1549 pid = tcp->pid;
1550 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1551 return -1;
1552 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1553 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001554 /* store "ri" in low two bits */
1555 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001556
1557 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001558 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1559 0);
1560 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1561 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001562 if (errno) {
1563 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1564 return -1;
1565 }
1566
1567 errno = 0;
1568 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1569 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1570 if (errno) {
1571 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1572 return -1;
1573 }
1574 tcp->flags |= TCB_BPTSET;
1575 }
1576#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001577
Michal Ludvig0e035502002-09-23 15:41:01 +00001578#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001579#define LOOP 0x0000feeb
1580#elif defined (M68K)
1581#define LOOP 0x60fe0000
1582#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001583#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001584#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001585#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001586#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001587#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001588#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001589#define LOOP 0x1000ffff
1590#elif defined(S390)
1591#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001592#elif defined(S390X)
1593#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001594#elif defined(HPPA)
1595#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001596#elif defined(SH)
1597#ifdef __LITTLE_ENDIAN__
1598#define LOOP 0x0000affe
1599#else
1600#define LOOP 0xfeaf0000
1601#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001602#else
1603#error unknown architecture
1604#endif
1605
1606 if (tcp->flags & TCB_BPTSET) {
1607 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1608 return -1;
1609 }
1610#if defined (I386)
1611 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1612 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001613#elif defined (X86_64)
1614 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1615 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616#elif defined (M68K)
1617 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1618 return -1;
1619#elif defined (ALPHA)
1620 return -1;
1621#elif defined (ARM)
1622 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001623#elif defined (MIPS)
1624 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001626 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001627 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001628#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001629 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1630 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001631#elif defined(HPPA)
1632 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1633 return -1;
1634 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001635#elif defined(SH)
1636 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1637 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638#else
1639#error unknown architecture
1640#endif
1641 if (debug)
1642 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1643 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1644 if (errno) {
1645 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1646 return -1;
1647 }
1648 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1649 if (errno) {
1650 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1651 return -1;
1652 }
1653 tcp->flags |= TCB_BPTSET;
1654
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001655#endif /* !IA64 */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001656#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001657#endif /* LINUX */
1658
1659#ifdef SUNOS4
1660#ifdef SPARC /* This code is slightly sparc specific */
1661
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001662 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663#define BPT 0x91d02001 /* ta 1 */
1664#define LOOP 0x10800000 /* ba 0 */
1665#define LOOPA 0x30800000 /* ba,a 0 */
1666#define NOP 0x01000000
1667#if LOOPA
1668 static int loopdeloop[1] = {LOOPA};
1669#else
1670 static int loopdeloop[2] = {LOOP, NOP};
1671#endif
1672
1673 if (tcp->flags & TCB_BPTSET) {
1674 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1675 return -1;
1676 }
1677 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1678 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1679 return -1;
1680 }
1681 tcp->baddr = regs.r_o7 + 8;
1682 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1683 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1684 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1685 return -1;
1686 }
1687
1688 /*
1689 * XXX - BRUTAL MODE ON
1690 * We cannot set a real BPT in the child, since it will not be
1691 * traced at the moment it will reach the trap and would probably
1692 * die with a core dump.
1693 * Thus, we are force our way in by taking out two instructions
1694 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1695 * generated by out PTRACE_ATTACH.
1696 * Of cause, if we evaporate ourselves in the middle of all this...
1697 */
1698 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1699 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1700 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1701 return -1;
1702 }
1703 tcp->flags |= TCB_BPTSET;
1704
1705#endif /* SPARC */
1706#endif /* SUNOS4 */
1707
1708 return 0;
1709}
1710
1711int
1712clearbpt(tcp)
1713struct tcb *tcp;
1714{
1715
1716#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001717#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001719#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001721#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001723#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001725#elif defined(HPPA)
1726 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001727#elif defined(SH)
1728 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001729#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001731#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 /* Again, we borrow the SunOS breakpoint code. */
1733 if (!(tcp->flags & TCB_BPTSET)) {
1734 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1735 return -1;
1736 }
1737 errno = 0;
1738 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1739 if(errno) {
1740 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1741 return -1;
1742 }
1743 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001744#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001745 if (ia32) {
1746 unsigned long addr;
1747
1748 if (debug)
1749 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1750 if (!(tcp->flags & TCB_BPTSET)) {
1751 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1752 return -1;
1753 }
1754 errno = 0;
1755 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1756 if (errno) {
1757 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1758 return -1;
1759 }
1760 tcp->flags &= ~TCB_BPTSET;
1761
1762 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1763 return -1;
1764 if (addr != tcp->baddr) {
1765 /* The breakpoint has not been reached yet. */
1766 if (debug)
1767 fprintf(stderr,
1768 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1769 addr, tcp->baddr);
1770 return 0;
1771 }
1772 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001773 unsigned long addr, ipsr;
1774 pid_t pid;
1775
1776 pid = tcp->pid;
1777
1778 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1779 return -1;
1780 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1781 return -1;
1782
1783 /* restore original bundle: */
1784 errno = 0;
1785 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1786 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1787 if (errno) {
1788 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1789 return -1;
1790 }
1791
1792 /* restore original "ri" in ipsr: */
1793 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1794 errno = 0;
1795 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1796 if (errno) {
1797 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1798 return -1;
1799 }
1800
1801 tcp->flags &= ~TCB_BPTSET;
1802
1803 if (addr != (tcp->baddr & ~0x3)) {
1804 /* the breakpoint has not been reached yet. */
1805 if (debug)
1806 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1807 addr, tcp->baddr);
1808 return 0;
1809 }
1810 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001811#else /* !IA64 && !SPARC && !SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812
1813 if (debug)
1814 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1815 if (!(tcp->flags & TCB_BPTSET)) {
1816 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1817 return -1;
1818 }
1819 errno = 0;
1820 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1821 if (errno) {
1822 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1823 return -1;
1824 }
1825 tcp->flags &= ~TCB_BPTSET;
1826
1827#ifdef I386
1828 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1829 return -1;
1830 if (eip != tcp->baddr) {
1831 /* The breakpoint has not been reached yet. */
1832 if (debug)
1833 fprintf(stderr,
1834 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1835 eip, tcp->baddr);
1836 return 0;
1837 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001838#elif defined(X86_64)
1839 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1840 return -1;
1841 if (eip != tcp->baddr) {
1842 /* The breakpoint has not been reached yet. */
1843 if (debug)
1844 fprintf(stderr,
1845 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1846 eip, tcp->baddr);
1847 return 0;
1848 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001849#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001850 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001851 return -1;
1852 if (pc != tcp->baddr) {
1853 /* The breakpoint has not been reached yet. */
1854 if (debug)
1855 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1856 pc, tcp->baddr);
1857 return 0;
1858 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001859#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001860 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1861 return -1;
1862 if (pc != tcp->baddr) {
1863 /* The breakpoint has not been reached yet. */
1864 if (debug)
1865 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1866 pc, tcp->baddr);
1867 return 0;
1868 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001869#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001870 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1871 return -1;
1872 if (pc != tcp->baddr) {
1873 /* The breakpoint has not been reached yet. */
1874 if (debug)
1875 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1876 pc, tcp->baddr);
1877 return 0;
1878 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001879#elif defined(HPPA)
1880 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1881 return -1;
1882 iaoq &= ~0x03;
1883 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1884 /* The breakpoint has not been reached yet. */
1885 if (debug)
1886 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1887 iaoq, tcp->baddr);
1888 return 0;
1889 }
1890 iaoq = tcp->baddr | 3;
1891 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1892 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1893 * has no significant effect.
1894 */
1895 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1896 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001897#elif defined(SH)
1898 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1899 return -1;
1900 if (pc != tcp->baddr) {
1901 /* The breakpoint has not been reached yet. */
1902 if (debug)
1903 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1904 pc, tcp->baddr);
1905 return 0;
1906 }
1907
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001908#endif /* arch */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001909#endif /* !SPARC && !SPARC64 && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001910#endif /* LINUX */
1911
1912#ifdef SUNOS4
1913#ifdef SPARC
1914
1915#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001916 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001917#endif
1918
1919 if (!(tcp->flags & TCB_BPTSET)) {
1920 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1921 return -1;
1922 }
1923 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1924 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1925 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1926 return -1;
1927 }
1928 tcp->flags &= ~TCB_BPTSET;
1929
1930#if !LOOPA
1931 /*
1932 * Since we don't have a single instruction breakpoint, we may have
1933 * to adjust the program counter after removing the our `breakpoint'.
1934 */
1935 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1936 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1937 return -1;
1938 }
1939 if ((regs.r_pc < tcp->baddr) ||
1940 (regs.r_pc > tcp->baddr + 4)) {
1941 /* The breakpoint has not been reached yet */
1942 if (debug)
1943 fprintf(stderr,
1944 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1945 regs.r_pc, tcp->parent->baddr);
1946 return 0;
1947 }
1948 if (regs.r_pc != tcp->baddr)
1949 if (debug)
1950 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1951 regs.r_pc, tcp->baddr);
1952
1953 regs.r_pc = tcp->baddr;
1954 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1955 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1956 return -1;
1957 }
1958#endif /* LOOPA */
1959#endif /* SPARC */
1960#endif /* SUNOS4 */
1961
1962 return 0;
1963}
1964
Roland McGrathd81f1d92003-01-09 06:53:34 +00001965#endif
1966
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001967#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001968
1969#ifdef SUNOS4
1970
1971static int
1972getex(pid, hdr)
1973int pid;
1974struct exec *hdr;
1975{
1976 int n;
1977
1978 for (n = 0; n < sizeof *hdr; n += 4) {
1979 long res;
1980 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1981 return -1;
1982 memcpy(((char *) hdr) + n, &res, 4);
1983 }
1984 if (debug) {
1985 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1986 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1987 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1988 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1989 }
1990 return 0;
1991}
1992
1993int
1994fixvfork(tcp)
1995struct tcb *tcp;
1996{
1997 int pid = tcp->pid;
1998 /*
1999 * Change `vfork' in a freshly exec'ed dynamically linked
2000 * executable's (internal) symbol table to plain old `fork'
2001 */
2002
2003 struct exec hdr;
2004 struct link_dynamic dyn;
2005 struct link_dynamic_2 ld;
2006 char *strtab, *cp;
2007
2008 if (getex(pid, &hdr) < 0)
2009 return -1;
2010 if (!hdr.a_dynamic)
2011 return -1;
2012
2013 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2014 fprintf(stderr, "Cannot read DYNAMIC\n");
2015 return -1;
2016 }
2017 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2018 fprintf(stderr, "Cannot read link_dynamic_2\n");
2019 return -1;
2020 }
2021 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2022 fprintf(stderr, "fixvfork: out of memory\n");
2023 return -1;
2024 }
2025 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2026 (int)ld.ld_symb_size, strtab) < 0)
2027 goto err;
2028
2029#if 0
2030 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2031 fprintf(stderr, "[symbol: %s]\n", cp);
2032 cp += strlen(cp)+1;
2033 }
2034 return 0;
2035#endif
2036 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2037 if (strcmp(cp, "_vfork") == 0) {
2038 if (debug)
2039 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2040 strcpy(cp, "_fork");
2041 break;
2042 }
2043 cp += strlen(cp)+1;
2044 }
2045 if (cp < strtab + ld.ld_symb_size)
2046 /*
2047 * Write entire symbol table back to avoid
2048 * memory alignment bugs in ptrace
2049 */
2050 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2051 (int)ld.ld_symb_size, strtab) < 0)
2052 goto err;
2053
2054 free(strtab);
2055 return 0;
2056
2057err:
2058 free(strtab);
2059 return -1;
2060}
2061
2062#endif /* SUNOS4 */