blob: 3a3db0a290aed62b00c9cb122703f26aac762db9 [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
66#include <linux/ptrace.h>
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000067#endif
68
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
70#include <sys/utsname.h>
71#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
72
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000073#if defined(LINUX) && defined(SPARC)
74
Roland McGrath4db26242003-01-30 20:15:19 +000075# define fpq kernel_fpq
76# define fq kernel_fq
77# define fpu kernel_fpu
78# include <asm/reg.h>
79# undef fpq
80# undef fq
81# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
83#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
85#include <linux/unistd.h>
86
87#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
88 type5,arg5,syscall) \
89type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
90{ \
91 long __res; \
92\
93__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
94 "or %%g0, %2, %%o1\n\t" \
95 "or %%g0, %3, %%o2\n\t" \
96 "or %%g0, %4, %%o3\n\t" \
97 "or %%g0, %5, %%o4\n\t" \
98 "or %%g0, %6, %%g1\n\t" \
99 "t 0x10\n\t" \
100 "bcc 1f\n\t" \
101 "or %%g0, %%o0, %0\n\t" \
102 "sub %%g0, %%o0, %0\n\t" \
103 "1:\n\t" \
104 : "=r" (__res) \
105 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
106 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
107 "i" (__NR_##syscall) \
108 : "g1", "o0", "o1", "o2", "o3", "o4"); \
109if (__res>=0) \
110 return (type) __res; \
111errno = -__res; \
112return -1; \
113}
114
115static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
116
117#define _ptrace
118
119#endif
120
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000121#endif
122
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123/* macros */
124#ifndef MAX
125#define MAX(a,b) (((a) > (b)) ? (a) : (b))
126#endif
127#ifndef MIN
128#define MIN(a,b) (((a) < (b)) ? (a) : (b))
129#endif
130
131void
132tv_tv(tv, a, b)
133struct timeval *tv;
134int a;
135int b;
136{
137 tv->tv_sec = a;
138 tv->tv_usec = b;
139}
140
141int
142tv_nz(a)
143struct timeval *a;
144{
145 return a->tv_sec || a->tv_usec;
146}
147
148int
149tv_cmp(a, b)
150struct timeval *a, *b;
151{
152 if (a->tv_sec < b->tv_sec
153 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
154 return -1;
155 if (a->tv_sec > b->tv_sec
156 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
157 return 1;
158 return 0;
159}
160
161double
162tv_float(tv)
163struct timeval *tv;
164{
165 return tv->tv_sec + tv->tv_usec/1000000.0;
166}
167
168void
169tv_add(tv, a, b)
170struct timeval *tv, *a, *b;
171{
172 tv->tv_sec = a->tv_sec + b->tv_sec;
173 tv->tv_usec = a->tv_usec + b->tv_usec;
174 if (tv->tv_usec > 1000000) {
175 tv->tv_sec++;
176 tv->tv_usec -= 1000000;
177 }
178}
179
180void
181tv_sub(tv, a, b)
182struct timeval *tv, *a, *b;
183{
184 tv->tv_sec = a->tv_sec - b->tv_sec;
185 tv->tv_usec = a->tv_usec - b->tv_usec;
186 if (((long) tv->tv_usec) < 0) {
187 tv->tv_sec--;
188 tv->tv_usec += 1000000;
189 }
190}
191
192void
193tv_div(tv, a, n)
194struct timeval *tv, *a;
195int n;
196{
197 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
198 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
199 tv->tv_usec %= 1000000;
200}
201
202void
203tv_mul(tv, a, n)
204struct timeval *tv, *a;
205int n;
206{
207 tv->tv_usec = a->tv_usec * n;
208 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
209 tv->tv_usec %= 1000000;
210}
211
212char *
213xlookup(xlat, val)
214struct xlat *xlat;
215int val;
216{
217 for (; xlat->str != NULL; xlat++)
218 if (xlat->val == val)
219 return xlat->str;
220 return NULL;
221}
222
223/*
224 * Print entry in struct xlat table, if there.
225 */
226void
227printxval(xlat, val, dflt)
228struct xlat *xlat;
229int val;
230char *dflt;
231{
232 char *str = xlookup(xlat, val);
233
234 if (str)
235 tprintf("%s", str);
236 else
237 tprintf("%#x /* %s */", val, dflt);
238}
239
240/*
241 * Interpret `xlat' as an array of flags
242 * print the entries whose bits are on in `flags'
243 * return # of flags printed.
244 */
245int
246addflags(xlat, flags)
247struct xlat *xlat;
248int flags;
249{
250 int n;
251
252 for (n = 0; xlat->str; xlat++) {
253 if (xlat->val && (flags & xlat->val) == xlat->val) {
254 tprintf("|%s", xlat->str);
255 flags &= ~xlat->val;
256 n++;
257 }
258 }
259 if (flags) {
260 tprintf("|%#x", flags);
261 n++;
262 }
263 return n;
264}
265
266int
267printflags(xlat, flags)
268struct xlat *xlat;
269int flags;
270{
271 int n;
272 char *sep;
273
274 if (flags == 0 && xlat->val == 0) {
275 tprintf("%s", xlat->str);
276 return 1;
277 }
278
279 sep = "";
280 for (n = 0; xlat->str; xlat++) {
281 if (xlat->val && (flags & xlat->val) == xlat->val) {
282 tprintf("%s%s", sep, xlat->str);
283 flags &= ~xlat->val;
284 sep = "|";
285 n++;
286 }
287 }
288 if (flags) {
289 tprintf("%s%#x", sep, flags);
290 n++;
291 }
292 return n;
293}
294
295void
296printnum(tcp, addr, fmt)
297struct tcb *tcp;
298long addr;
299char *fmt;
300{
Roland McGratheb285352003-01-14 09:59:00 +0000301 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302
303 if (!addr) {
304 tprintf("NULL");
305 return;
306 }
307 if (umove(tcp, addr, &num) < 0) {
308 tprintf("%#lx", addr);
309 return;
310 }
311 tprintf("[");
312 tprintf(fmt, num);
313 tprintf("]");
314}
315
Roland McGrath6bc12202003-11-13 22:32:27 +0000316void
317printuid(text, uid)
318const char *text;
319unsigned long uid;
320{
321 tprintf("%s", text);
322 tprintf((uid == -1) ? "%ld" : "%lu", uid);
323}
324
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000325static char path[MAXPATHLEN + 1];
326
327void
328string_quote(str)
329char *str;
330{
331 char buf[2 * MAXPATHLEN + 1];
332 char *s;
333
334 if (!strpbrk(str, "\"\'\\")) {
335 tprintf("\"%s\"", str);
336 return;
337 }
338 for (s = buf; *str; str++) {
339 switch (*str) {
340 case '\"': case '\'': case '\\':
341 *s++ = '\\'; *s++ = *str; break;
342 default:
343 *s++ = *str; break;
344 }
345 }
346 *s = '\0';
347 tprintf("\"%s\"", buf);
348}
349
350void
351printpath(tcp, addr)
352struct tcb *tcp;
353long addr;
354{
355 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
356 tprintf("%#lx", addr);
357 else
358 string_quote(path);
359 return;
360}
361
362void
363printpathn(tcp, addr, n)
364struct tcb *tcp;
365long addr;
366int n;
367{
368 if (umovestr(tcp, addr, n, path) < 0)
369 tprintf("%#lx", addr);
370 else {
371 path[n] = '\0';
372 string_quote(path);
373 }
374}
375
376void
377printstr(tcp, addr, len)
378struct tcb *tcp;
379long addr;
380int len;
381{
382 static unsigned char *str = NULL;
383 static char *outstr;
384 int i, n, c, usehex;
385 char *s, *outend;
386
387 if (!addr) {
388 tprintf("NULL");
389 return;
390 }
391 if (!str) {
392 if ((str = malloc(max_strlen)) == NULL
393 || (outstr = malloc(2*max_strlen)) == NULL) {
394 fprintf(stderr, "printstr: no memory\n");
395 tprintf("%#lx", addr);
396 return;
397 }
398 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000399 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000400 if (len < 0) {
401 n = max_strlen;
402 if (umovestr(tcp, addr, n, (char *) str) < 0) {
403 tprintf("%#lx", addr);
404 return;
405 }
406 }
407 else {
408 n = MIN(len, max_strlen);
409 if (umoven(tcp, addr, n, (char *) str) < 0) {
410 tprintf("%#lx", addr);
411 return;
412 }
413 }
414
415 usehex = 0;
416 if (xflag > 1)
417 usehex = 1;
418 else if (xflag) {
419 for (i = 0; i < n; i++) {
420 c = str[i];
421 if (len < 0 && c == '\0')
422 break;
423 if (!isprint(c) && !isspace(c)) {
424 usehex = 1;
425 break;
426 }
427 }
428 }
429
430 s = outstr;
431 *s++ = '\"';
432
433 if (usehex) {
434 for (i = 0; i < n; i++) {
435 c = str[i];
436 if (len < 0 && c == '\0')
437 break;
438 sprintf(s, "\\x%02x", c);
439 s += 4;
440 if (s > outend)
441 break;
442 }
443 }
444 else {
445 for (i = 0; i < n; i++) {
446 c = str[i];
447 if (len < 0 && c == '\0')
448 break;
449 switch (c) {
450 case '\"': case '\'': case '\\':
451 *s++ = '\\'; *s++ = c; break;
452 case '\f':
453 *s++ = '\\'; *s++ = 'f'; break;
454 case '\n':
455 *s++ = '\\'; *s++ = 'n'; break;
456 case '\r':
457 *s++ = '\\'; *s++ = 'r'; break;
458 case '\t':
459 *s++ = '\\'; *s++ = 't'; break;
460 case '\v':
461 *s++ = '\\'; *s++ = 'v'; break;
462 default:
463 if (isprint(c))
464 *s++ = c;
465 else if (i < n - 1 && isdigit(str[i + 1])) {
466 sprintf(s, "\\%03o", c);
467 s += 4;
468 }
469 else {
470 sprintf(s, "\\%o", c);
471 s += strlen(s);
472 }
473 break;
474 }
475 if (s > outend)
476 break;
477 }
478 }
479
480 *s++ = '\"';
481 if (i < len || (len < 0 && (i == n || s > outend))) {
482 *s++ = '.'; *s++ = '.'; *s++ = '.';
483 }
484 *s = '\0';
485 tprintf("%s", outstr);
486}
487
John Hughes1d08dcf2001-07-10 13:48:44 +0000488#if HAVE_SYS_UIO_H
489void
490dumpiov(tcp, len, addr)
491struct tcb * tcp;
492int len;
493long addr;
494{
495 struct iovec *iov;
496 int i;
497
Roland McGrath1e85cf92002-12-16 20:40:54 +0000498
John Hughes1d08dcf2001-07-10 13:48:44 +0000499 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
500 fprintf(stderr, "dump: No memory");
501 return;
502 }
503 if (umoven(tcp, addr,
504 len * sizeof *iov, (char *) iov) >= 0) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000505
John Hughes1d08dcf2001-07-10 13:48:44 +0000506 for (i = 0; i < len; i++) {
507 /* include the buffer number to make it easy to
508 * match up the trace with the source */
509 tprintf(" * %lu bytes in buffer %d\n",
510 (unsigned long)iov[i].iov_len, i);
511 dumpstr(tcp, (long) iov[i].iov_base,
512 iov[i].iov_len);
513 }
514 }
515 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000516
John Hughes1d08dcf2001-07-10 13:48:44 +0000517}
518#endif
519
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520void
521dumpstr(tcp, addr, len)
522struct tcb *tcp;
523long addr;
524int len;
525{
526 static int strsize = -1;
527 static unsigned char *str;
528 static char outstr[80];
529 char *s;
530 int i, j;
531
532 if (strsize < len) {
533 if (str)
534 free(str);
535 if ((str = malloc(len)) == NULL) {
536 fprintf(stderr, "dump: no memory\n");
537 return;
538 }
539 strsize = len;
540 }
541
542 if (umoven(tcp, addr, len, (char *) str) < 0)
543 return;
544
545 for (i = 0; i < len; i += 16) {
546 s = outstr;
547 sprintf(s, " | %05x ", i);
548 s += 9;
549 for (j = 0; j < 16; j++) {
550 if (j == 8)
551 *s++ = ' ';
552 if (i + j < len) {
553 sprintf(s, " %02x", str[i + j]);
554 s += 3;
555 }
556 else {
557 *s++ = ' '; *s++ = ' '; *s++ = ' ';
558 }
559 }
560 *s++ = ' '; *s++ = ' ';
561 for (j = 0; j < 16; j++) {
562 if (j == 8)
563 *s++ = ' ';
564 if (i + j < len) {
565 if (isprint(str[i + j]))
566 *s++ = str[i + j];
567 else
568 *s++ = '.';
569 }
570 else
571 *s++ = ' ';
572 }
573 tprintf("%s |\n", outstr);
574 }
575}
576
577#define PAGMASK (~(PAGSIZ - 1))
578/*
579 * move `len' bytes of data from process `pid'
580 * at address `addr' to our space at `laddr'
581 */
582int
583umoven(tcp, addr, len, laddr)
584struct tcb *tcp;
585long addr;
586int len;
587char *laddr;
588{
589
590#ifdef LINUX
591 int pid = tcp->pid;
592 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000593 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000594 union {
595 long val;
596 char x[sizeof(long)];
597 } u;
598
599 if (addr & (sizeof(long) - 1)) {
600 /* addr not a multiple of sizeof(long) */
601 n = addr - (addr & -sizeof(long)); /* residue */
602 addr &= -sizeof(long); /* residue */
603 errno = 0;
604 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
605 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000606 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607 /* Ran into 'end of memory' - stupid "printpath" */
608 return 0;
609 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000610 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000611 perror("ptrace: umoven");
612 return -1;
613 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000614 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000615 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
616 addr += sizeof(long), laddr += m, len -= m;
617 }
618 while (len) {
619 errno = 0;
620 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
621 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000622 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000623 /* Ran into 'end of memory' - stupid "printpath" */
624 return 0;
625 }
Roland McGrath4db26242003-01-30 20:15:19 +0000626 if (addr != 0)
627 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000628 return -1;
629 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000630 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
632 addr += sizeof(long), laddr += m, len -= m;
633 }
634#endif /* LINUX */
635
636#ifdef SUNOS4
637 int pid = tcp->pid;
638#if 0
639 int n, m;
640 union {
641 long val;
642 char x[sizeof(long)];
643 } u;
644
645 if (addr & (sizeof(long) - 1)) {
646 /* addr not a multiple of sizeof(long) */
647 n = addr - (addr & -sizeof(long)); /* residue */
648 addr &= -sizeof(long); /* residue */
649 errno = 0;
650 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
651 if (errno) {
652 perror("umoven");
653 return -1;
654 }
655 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
656 addr += sizeof(long), laddr += m, len -= m;
657 }
658 while (len) {
659 errno = 0;
660 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
661 if (errno) {
662 perror("umoven");
663 return -1;
664 }
665 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
666 addr += sizeof(long), laddr += m, len -= m;
667 }
668#else /* !oldway */
669 int n;
670
671 while (len) {
672 n = MIN(len, PAGSIZ);
673 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
674 if (ptrace(PTRACE_READDATA, pid,
675 (char *) addr, len, laddr) < 0) {
676 perror("umoven: ptrace(PTRACE_READDATA, ...)");
677 abort();
678 return -1;
679 }
680 len -= n;
681 addr += n;
682 laddr += n;
683 }
684#endif /* !oldway */
685#endif /* SUNOS4 */
686
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000687#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000688#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000689 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000690#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000691 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000693 lseek(fd, addr, SEEK_SET);
694 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000696#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697
698 return 0;
699}
700
701/*
702 * like `umove' but make the additional effort of looking
703 * for a terminating zero byte.
704 */
705int
706umovestr(tcp, addr, len, laddr)
707struct tcb *tcp;
708long addr;
709int len;
710char *laddr;
711{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000712#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000713#ifdef HAVE_MP_PROCFS
714 int fd = tcp->pfd_as;
715#else
716 int fd = tcp->pfd;
717#endif
718 /* Some systems (e.g. FreeBSD) can be upset if we read off the
719 end of valid memory, avoid this by trying to read up
720 to page boundaries. But we don't know what a page is (and
721 getpagesize(2) (if it exists) doesn't necessarily return
722 hardware page size). Assume all pages >= 1024 (a-historical
723 I know) */
724
725 int page = 1024; /* How to find this? */
726 int move = page - (addr & (page - 1));
727 int left = len;
728
729 lseek(fd, addr, SEEK_SET);
730
731 while (left) {
732 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000733 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000734 return left != len ? 0 : -1;
735 if (memchr (laddr, 0, move)) break;
736 left -= move;
737 laddr += move;
738 addr += move;
739 move = page;
740 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000741#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000742 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000743 int pid = tcp->pid;
744 int i, n, m;
745 union {
746 long val;
747 char x[sizeof(long)];
748 } u;
749
750 if (addr & (sizeof(long) - 1)) {
751 /* addr not a multiple of sizeof(long) */
752 n = addr - (addr & -sizeof(long)); /* residue */
753 addr &= -sizeof(long); /* residue */
754 errno = 0;
755 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
756 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000757 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000758 /* Ran into 'end of memory' - stupid "printpath" */
759 return 0;
760 }
761 perror("umovestr");
762 return -1;
763 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000764 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000765 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
766 while (n & (sizeof(long) - 1))
767 if (u.x[n++] == '\0')
768 return 0;
769 addr += sizeof(long), laddr += m, len -= m;
770 }
771 while (len) {
772 errno = 0;
773 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
774 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000775 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776 /* Ran into 'end of memory' - stupid "printpath" */
777 return 0;
778 }
779 perror("umovestr");
780 return -1;
781 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000782 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
784 for (i = 0; i < sizeof(long); i++)
785 if (u.x[i] == '\0')
786 return 0;
787
788 addr += sizeof(long), laddr += m, len -= m;
789 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000790#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000791 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792}
793
794#ifdef LINUX
795#ifndef SPARC
796#define PTRACE_WRITETEXT 101
797#define PTRACE_WRITEDATA 102
798#endif /* !SPARC */
799#endif /* LINUX */
800
801#ifdef SUNOS4
802
803static int
804uload(cmd, pid, addr, len, laddr)
805int cmd;
806int pid;
807long addr;
808int len;
809char *laddr;
810{
811#if 0
812 int n;
813
814 while (len) {
815 n = MIN(len, PAGSIZ);
816 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
817 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
818 perror("uload: ptrace(PTRACE_WRITE, ...)");
819 return -1;
820 }
821 len -= n;
822 addr += n;
823 laddr += n;
824 }
825#else
826 int peek, poke;
827 int n, m;
828 union {
829 long val;
830 char x[sizeof(long)];
831 } u;
832
833 if (cmd == PTRACE_WRITETEXT) {
834 peek = PTRACE_PEEKTEXT;
835 poke = PTRACE_POKETEXT;
836 }
837 else {
838 peek = PTRACE_PEEKDATA;
839 poke = PTRACE_POKEDATA;
840 }
841 if (addr & (sizeof(long) - 1)) {
842 /* addr not a multiple of sizeof(long) */
843 n = addr - (addr & -sizeof(long)); /* residue */
844 addr &= -sizeof(long);
845 errno = 0;
846 u.val = ptrace(peek, pid, (char *) addr, 0);
847 if (errno) {
848 perror("uload: POKE");
849 return -1;
850 }
851 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
852 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
853 perror("uload: POKE");
854 return -1;
855 }
856 addr += sizeof(long), laddr += m, len -= m;
857 }
858 while (len) {
859 if (len < sizeof(long))
860 u.val = ptrace(peek, pid, (char *) addr, 0);
861 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
862 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
863 perror("uload: POKE");
864 return -1;
865 }
866 addr += sizeof(long), laddr += m, len -= m;
867 }
868#endif
869 return 0;
870}
871
872int
873tload(pid, addr, len, laddr)
874int pid;
875int addr, len;
876char *laddr;
877{
878 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
879}
880
881int
882dload(pid, addr, len, laddr)
883int pid;
884int addr;
885int len;
886char *laddr;
887{
888 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
889}
890
891#endif /* SUNOS4 */
892
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000893#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894
895int
896upeek(pid, off, res)
897int pid;
898long off;
899long *res;
900{
901 long val;
902
903#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
904 {
905 static int is_sun4m = -1;
906 struct utsname name;
907
908 /* Round up the usual suspects. */
909 if (is_sun4m == -1) {
910 if (uname(&name) < 0) {
911 perror("upeek: uname?");
912 exit(1);
913 }
914 is_sun4m = strcmp(name.machine, "sun4m") == 0;
915 if (is_sun4m) {
916 extern struct xlat struct_user_offsets[];
917 struct xlat *x;
918
919 for (x = struct_user_offsets; x->str; x++)
920 x->val += 1024;
921 }
922 }
923 if (is_sun4m)
924 off += 1024;
925 }
926#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
927 errno = 0;
928 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
929 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000930 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000931 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000932 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933 return -1;
934 }
935 *res = val;
936 return 0;
937}
938
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000939#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940
941long
942getpc(tcp)
943struct tcb *tcp;
944{
945
946#ifdef LINUX
947 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000948#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
950 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000951#elif defined(X86_64)
952 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
953 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000954#elif defined(IA64)
955 if (upeek(tcp->pid, PT_B0, &pc) < 0)
956 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000957#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 if (upeek(tcp->pid, 4*15, &pc) < 0)
959 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000960#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000961 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000963#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000964 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
965 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000966#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 if (upeek(tcp->pid, REG_PC, &pc) < 0)
968 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000969#elif defined(MIPS)
970 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
971 return -1;
972#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000973 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000974 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
975 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000976 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000977#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000978 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +0000979 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000980#elif defined(HPPA)
981 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
982 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000983#elif defined(SH)
984 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
985 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +0000986#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +0000987 if (upeek(tcp->pid, REG_PC ,&pc) < 0)
988 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +0000989#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990 return pc;
991#endif /* LINUX */
992
993#ifdef SUNOS4
994 /*
995 * Return current program counter for `pid'
996 * Assumes PC is never 0xffffffff
997 */
998 struct regs regs;
999
1000 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1001 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1002 return -1;
1003 }
1004 return regs.r_pc;
1005#endif /* SUNOS4 */
1006
1007#ifdef SVR4
1008 /* XXX */
1009 return 0;
1010#endif /* SVR4 */
1011
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001012#ifdef FREEBSD
1013 struct reg regs;
1014 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1015 return regs.r_eip;
1016#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001017}
1018
1019void
1020printcall(tcp)
1021struct tcb *tcp;
1022{
1023
1024#ifdef LINUX
1025#ifdef I386
1026 long eip;
1027
1028 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1029 tprintf("[????????] ");
1030 return;
1031 }
1032 tprintf("[%08lx] ", eip);
Michal Ludvig0e035502002-09-23 15:41:01 +00001033#elif defined(X86_64)
1034 long rip;
1035
1036 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1037 tprintf("[????????] ");
1038 return;
1039 }
1040 tprintf("[%16lx] ", rip);
Roland McGrathef388682003-06-03 23:28:59 +00001041#elif defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001042 long ip;
1043
1044 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1045 tprintf("[????????] ");
1046 return;
1047 }
1048 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001049#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001050 long pc;
1051
Roland McGratheb285352003-01-14 09:59:00 +00001052 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001053 tprintf ("[????????] ");
1054 return;
1055 }
1056 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001057#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058 long pc;
1059
1060 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1061 tprintf ("[????????] ");
1062 return;
1063 }
1064 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001065#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001066 long pc;
1067
1068 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1069 tprintf ("[????????] ");
1070 return;
1071 }
1072 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001073#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001074 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001075 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1076 tprintf("[????????] ");
1077 return;
1078 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001079 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001080#elif defined(HPPA)
1081 long pc;
1082
1083 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1084 tprintf ("[????????] ");
1085 return;
1086 }
1087 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001088#elif defined(MIPS)
1089 long pc;
1090
1091 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1092 tprintf ("[????????] ");
1093 return;
1094 }
1095 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001096#elif defined(SH)
1097 long pc;
1098
1099 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1100 tprintf ("[????????] ");
1101 return;
1102 }
1103 tprintf("[%08lx] ", pc);
Roland McGrathf5a47772003-06-26 22:40:42 +00001104#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001105 long pc;
1106
1107 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1108 tprintf ("[????????] ");
1109 return;
1110 }
1111 tprintf("[%08lx] ", pc);
Roland McGrathef388682003-06-03 23:28:59 +00001112#elif defined(ARM)
1113 long pc;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001114
Roland McGrathef388682003-06-03 23:28:59 +00001115 if (upeek(tcp->pid, 4*15, &pc) < 0) {
1116 tprintf("[????????] ");
1117 return;
1118 }
1119 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001120#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001121#endif /* LINUX */
1122
1123#ifdef SUNOS4
1124 struct regs regs;
1125
1126 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1127 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1128 tprintf("[????????] ");
1129 return;
1130 }
1131 tprintf("[%08x] ", regs.r_o7);
1132#endif /* SUNOS4 */
1133
1134#ifdef SVR4
1135 /* XXX */
1136 tprintf("[????????] ");
1137#endif
1138
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001139#ifdef FREEBSD
1140 struct reg regs;
1141 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1142 tprintf("[%08x] ", regs.r_eip);
1143#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144}
1145
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001146#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147
Roland McGrathd81f1d92003-01-09 06:53:34 +00001148#if defined LINUX
1149
1150#include <sys/syscall.h>
1151#ifndef CLONE_PTRACE
1152# define CLONE_PTRACE 0x00002000
1153#endif
1154
1155#ifdef IA64
1156
Roland McGrath08267b82004-02-20 22:56:43 +00001157/* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1158 subsystem has them for x86... */
1159#define SYS_fork 2
1160#define SYS_vfork 190
1161
Roland McGrathd81f1d92003-01-09 06:53:34 +00001162typedef unsigned long *arg_setup_state;
1163
1164static int
1165arg_setup(struct tcb *tcp, arg_setup_state *state)
1166{
1167 unsigned long *bsp, cfm, sof, sol;
1168
Roland McGrath08267b82004-02-20 22:56:43 +00001169 if (ia32)
1170 return 0;
1171
Roland McGrathd81f1d92003-01-09 06:53:34 +00001172 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1173 return -1;
1174 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1175 return -1;
1176
1177 sof = (cfm >> 0) & 0x7f;
1178 sol = (cfm >> 7) & 0x7f;
1179 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1180
1181 *state = bsp;
1182 return 0;
1183}
1184
1185# define arg_finish_change(tcp, state) 0
1186
1187#ifdef SYS_fork
1188static int
1189get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1190{
Roland McGrath08267b82004-02-20 22:56:43 +00001191 int ret;
1192
1193 if (ia32)
1194 ret = upeek (tcp->pid, PT_R11, valp);
1195 else
1196 ret = umoven (tcp,
1197 (unsigned long) ia64_rse_skip_regs(*state, 0),
1198 sizeof(long), (void *) valp);
1199 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001200}
1201
1202static int
1203get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1204{
Roland McGrath08267b82004-02-20 22:56:43 +00001205 int ret;
1206
1207 if (ia32)
1208 ret = upeek (tcp->pid, PT_R9, valp);
1209 else
1210 ret = umoven (tcp,
1211 (unsigned long) ia64_rse_skip_regs(*state, 1),
1212 sizeof(long), (void *) valp);
1213 return ret;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001214}
1215#endif
1216
1217static int
1218set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1219{
Roland McGrath08267b82004-02-20 22:56:43 +00001220 int req = PTRACE_POKEDATA;
1221 void *ap;
1222
1223 if (ia32) {
1224 ap = (void *) (intptr_t) PT_R11; /* r11 == EBX */
1225 req = PTRACE_POKEUSER;
1226 } else
1227 ap = ia64_rse_skip_regs(*state, 0);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001228 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001229 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001230 return errno ? -1 : 0;
1231}
1232
1233static int
1234set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1235{
Roland McGrath08267b82004-02-20 22:56:43 +00001236 int req = PTRACE_POKEDATA;
1237 void *ap;
1238
1239 if (ia32) {
1240 ap = (void *) (intptr_t) PT_R9; /* r9 == ECX */
1241 req = PTRACE_POKEUSER;
1242 } else
1243 ap = ia64_rse_skip_regs(*state, 1);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001244 errno = 0;
Roland McGrath08267b82004-02-20 22:56:43 +00001245 ptrace(req, tcp->pid, ap, val);
Roland McGrathd81f1d92003-01-09 06:53:34 +00001246 return errno ? -1 : 0;
1247}
1248
1249#elif defined (SPARC)
1250
1251typedef struct regs arg_setup_state;
1252
1253# define arg_setup(tcp, state) \
1254 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1255# define arg_finish_change(tcp, state) \
1256 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1257
1258# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1259# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1260# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1261# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001262# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001263
1264#else
1265
1266# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001267/* Note: this is only true for the `clone' system call, which handles
1268 arguments specially. We could as well say that its first two arguments
1269 are swapped relative to other architectures, but that would just be
1270 another #ifdef in the calls. */
1271# define arg0_offset PT_GPR3
1272# define arg1_offset PT_ORIGGPR2
1273# define restore_arg0(tcp, state, val) ((void) (state), 0)
1274# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001275# define arg0_index 1
1276# define arg1_index 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001277# elif defined (ALPHA) || defined (MIPS)
1278# define arg0_offset REG_A0
1279# define arg1_offset (REG_A0+1)
1280# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001281# define arg0_offset (sizeof(unsigned long)*PT_R3)
1282# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001283# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284# elif defined (HPPA)
1285# define arg0_offset PT_GR26
1286# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001287# elif defined (X86_64)
1288# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1289# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001290# elif defined (SH)
1291# define arg0_offset (4*(REG_REG0+4))
1292# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001293# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001294 /* ABI defines arg0 & 1 in r2 & r3 */
1295# define arg0_offset (REG_OFFSET+16)
1296# define arg1_offset (REG_OFFSET+24)
1297# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001298# else
1299# define arg0_offset 0
1300# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001301# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001302# define restore_arg0(tcp, state, val) 0
1303# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001304# endif
1305
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001306# ifndef arg0_index
1307# define arg0_index 0
1308# define arg1_index 1
1309# endif
1310
Roland McGrathd81f1d92003-01-09 06:53:34 +00001311typedef int arg_setup_state;
1312
1313# define arg_setup(tcp, state) (0)
1314# define arg_finish_change(tcp, state) 0
1315# define get_arg0(tcp, cookie, valp) \
1316 (upeek ((tcp)->pid, arg0_offset, (valp)))
1317# define get_arg1(tcp, cookie, valp) \
1318 (upeek ((tcp)->pid, arg1_offset, (valp)))
1319
1320static int
1321set_arg0 (struct tcb *tcp, void *cookie, long val)
1322{
1323 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1324}
1325
1326static int
1327set_arg1 (struct tcb *tcp, void *cookie, long val)
1328{
1329 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1330}
1331
1332#endif
1333
Roland McGrathe1df47f2003-01-14 09:46:15 +00001334#ifndef restore_arg0
1335# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1336#endif
1337#ifndef restore_arg1
1338# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1339#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001340
1341int
1342setbpt(tcp)
1343struct tcb *tcp;
1344{
1345 extern int change_syscall(struct tcb *, int);
1346 arg_setup_state state;
1347
1348 if (tcp->flags & TCB_BPTSET) {
1349 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1350 return -1;
1351 }
1352
1353 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001354#ifdef SYS_vfork
1355 case SYS_vfork:
1356#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001357#ifdef SYS_fork
1358 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001359#endif
1360#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001361 if (arg_setup (tcp, &state) < 0
1362 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1363 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1364 || change_syscall(tcp, SYS_clone) < 0
1365 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1366 || set_arg1 (tcp, &state, 0) < 0
1367 || arg_finish_change (tcp, &state) < 0)
1368 return -1;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001369 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1370 tcp->u_arg[arg1_index] = 0;
Roland McGrathd81f1d92003-01-09 06:53:34 +00001371 tcp->flags |= TCB_BPTSET;
1372 return 0;
1373#endif
1374
1375 case SYS_clone:
1376#ifdef SYS_clone2
1377 case SYS_clone2:
1378#endif
1379 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1380 && (arg_setup (tcp, &state) < 0
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001381 || set_arg0 (tcp, &state,
1382 tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001383 || arg_finish_change (tcp, &state) < 0))
1384 return -1;
1385 tcp->flags |= TCB_BPTSET;
Roland McGrathc9dc3c12004-03-01 20:57:09 +00001386 tcp->inst[0] = tcp->u_arg[arg0_index];
1387 tcp->inst[1] = tcp->u_arg[arg1_index];
Roland McGrathd81f1d92003-01-09 06:53:34 +00001388 return 0;
1389
1390 default:
1391 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1392 tcp->scno, tcp->pid);
1393 break;
1394 }
1395
1396 return -1;
1397}
1398
1399int
1400clearbpt(tcp)
1401struct tcb *tcp;
1402{
1403 arg_setup_state state;
1404 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001405 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1406 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001407 || arg_finish_change (tcp, &state))
1408 return -1;
1409 tcp->flags &= ~TCB_BPTSET;
1410 return 0;
1411}
1412
1413#else
1414
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415int
1416setbpt(tcp)
1417struct tcb *tcp;
1418{
1419
1420#ifdef LINUX
1421#ifdef SPARC
1422 /* We simply use the SunOS breakpoint code. */
1423
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001424 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001425#define LOOPA 0x30800000 /* ba,a 0 */
1426
1427 if (tcp->flags & TCB_BPTSET) {
1428 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1429 return -1;
1430 }
1431 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1432 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1433 return -1;
1434 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001435 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 errno = 0;
1437 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1438 if(errno) {
1439 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1440 return -1;
1441 }
1442
1443 /*
1444 * XXX - BRUTAL MODE ON
1445 * We cannot set a real BPT in the child, since it will not be
1446 * traced at the moment it will reach the trap and would probably
1447 * die with a core dump.
1448 * Thus, we are force our way in by taking out two instructions
1449 * and insert an eternal loop instead, in expectance of the SIGSTOP
1450 * generated by out PTRACE_ATTACH.
1451 * Of cause, if we evaporate ourselves in the middle of all this...
1452 */
1453 errno = 0;
1454 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1455 if(errno) {
1456 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1457 return -1;
1458 }
1459 tcp->flags |= TCB_BPTSET;
1460
1461#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001462#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001463 if (ia32) {
1464# define LOOP 0x0000feeb
1465 if (tcp->flags & TCB_BPTSET) {
1466 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1467 tcp->pid);
1468 return -1;
1469 }
1470 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1471 return -1;
1472 if (debug)
1473 fprintf(stderr, "[%d] setting bpt at %lx\n",
1474 tcp->pid, tcp->baddr);
1475 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1476 (char *) tcp->baddr, 0);
1477 if (errno) {
1478 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1479 return -1;
1480 }
1481 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1482 if (errno) {
1483 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1484 return -1;
1485 }
1486 tcp->flags |= TCB_BPTSET;
1487 } else {
1488 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001489 * Our strategy here is to replace the bundle that
1490 * contained the clone() syscall with a bundle of the
1491 * form:
1492 *
1493 * { 1: br 1b; br 1b; br 1b }
1494 *
1495 * This ensures that the newly forked child will loop
1496 * endlessly until we've got a chance to attach to it.
1497 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001498# define LOOP0 0x0000100000000017
1499# define LOOP1 0x4000000000200000
1500 unsigned long addr, ipsr;
1501 pid_t pid;
1502
1503 pid = tcp->pid;
1504 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1505 return -1;
1506 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1507 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001508 /* store "ri" in low two bits */
1509 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001510
1511 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001512 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1513 0);
1514 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1515 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001516 if (errno) {
1517 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1518 return -1;
1519 }
1520
1521 errno = 0;
1522 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1523 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1524 if (errno) {
1525 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1526 return -1;
1527 }
1528 tcp->flags |= TCB_BPTSET;
1529 }
1530#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531
Michal Ludvig0e035502002-09-23 15:41:01 +00001532#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533#define LOOP 0x0000feeb
1534#elif defined (M68K)
1535#define LOOP 0x60fe0000
1536#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001537#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001539#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001540#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001541#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001542#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001543#define LOOP 0x1000ffff
1544#elif defined(S390)
1545#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001546#elif defined(S390X)
1547#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001548#elif defined(HPPA)
1549#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001550#elif defined(SH)
1551#ifdef __LITTLE_ENDIAN__
1552#define LOOP 0x0000affe
1553#else
1554#define LOOP 0xfeaf0000
1555#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001556#else
1557#error unknown architecture
1558#endif
1559
1560 if (tcp->flags & TCB_BPTSET) {
1561 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1562 return -1;
1563 }
1564#if defined (I386)
1565 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1566 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001567#elif defined (X86_64)
1568 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1569 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570#elif defined (M68K)
1571 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1572 return -1;
1573#elif defined (ALPHA)
1574 return -1;
1575#elif defined (ARM)
1576 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001577#elif defined (MIPS)
1578 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001579#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001580 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001582#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001583 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1584 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001585#elif defined(HPPA)
1586 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1587 return -1;
1588 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001589#elif defined(SH)
1590 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1591 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001592#else
1593#error unknown architecture
1594#endif
1595 if (debug)
1596 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1597 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1598 if (errno) {
1599 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1600 return -1;
1601 }
1602 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1603 if (errno) {
1604 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1605 return -1;
1606 }
1607 tcp->flags |= TCB_BPTSET;
1608
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001609#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610#endif /* SPARC */
1611#endif /* LINUX */
1612
1613#ifdef SUNOS4
1614#ifdef SPARC /* This code is slightly sparc specific */
1615
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001616 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617#define BPT 0x91d02001 /* ta 1 */
1618#define LOOP 0x10800000 /* ba 0 */
1619#define LOOPA 0x30800000 /* ba,a 0 */
1620#define NOP 0x01000000
1621#if LOOPA
1622 static int loopdeloop[1] = {LOOPA};
1623#else
1624 static int loopdeloop[2] = {LOOP, NOP};
1625#endif
1626
1627 if (tcp->flags & TCB_BPTSET) {
1628 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1629 return -1;
1630 }
1631 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1632 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1633 return -1;
1634 }
1635 tcp->baddr = regs.r_o7 + 8;
1636 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1637 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1638 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1639 return -1;
1640 }
1641
1642 /*
1643 * XXX - BRUTAL MODE ON
1644 * We cannot set a real BPT in the child, since it will not be
1645 * traced at the moment it will reach the trap and would probably
1646 * die with a core dump.
1647 * Thus, we are force our way in by taking out two instructions
1648 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1649 * generated by out PTRACE_ATTACH.
1650 * Of cause, if we evaporate ourselves in the middle of all this...
1651 */
1652 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1653 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1654 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1655 return -1;
1656 }
1657 tcp->flags |= TCB_BPTSET;
1658
1659#endif /* SPARC */
1660#endif /* SUNOS4 */
1661
1662 return 0;
1663}
1664
1665int
1666clearbpt(tcp)
1667struct tcb *tcp;
1668{
1669
1670#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001671#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001673#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001674 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001675#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001676 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001677#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001679#elif defined(HPPA)
1680 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001681#elif defined(SH)
1682 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001683#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684
1685#ifdef SPARC
1686 /* Again, we borrow the SunOS breakpoint code. */
1687 if (!(tcp->flags & TCB_BPTSET)) {
1688 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1689 return -1;
1690 }
1691 errno = 0;
1692 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1693 if(errno) {
1694 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1695 return -1;
1696 }
1697 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001698#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001699 if (ia32) {
1700 unsigned long addr;
1701
1702 if (debug)
1703 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1704 if (!(tcp->flags & TCB_BPTSET)) {
1705 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1706 return -1;
1707 }
1708 errno = 0;
1709 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1710 if (errno) {
1711 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1712 return -1;
1713 }
1714 tcp->flags &= ~TCB_BPTSET;
1715
1716 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1717 return -1;
1718 if (addr != tcp->baddr) {
1719 /* The breakpoint has not been reached yet. */
1720 if (debug)
1721 fprintf(stderr,
1722 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1723 addr, tcp->baddr);
1724 return 0;
1725 }
1726 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001727 unsigned long addr, ipsr;
1728 pid_t pid;
1729
1730 pid = tcp->pid;
1731
1732 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1733 return -1;
1734 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1735 return -1;
1736
1737 /* restore original bundle: */
1738 errno = 0;
1739 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1740 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1741 if (errno) {
1742 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1743 return -1;
1744 }
1745
1746 /* restore original "ri" in ipsr: */
1747 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1748 errno = 0;
1749 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1750 if (errno) {
1751 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1752 return -1;
1753 }
1754
1755 tcp->flags &= ~TCB_BPTSET;
1756
1757 if (addr != (tcp->baddr & ~0x3)) {
1758 /* the breakpoint has not been reached yet. */
1759 if (debug)
1760 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1761 addr, tcp->baddr);
1762 return 0;
1763 }
1764 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001765#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001766
1767 if (debug)
1768 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1769 if (!(tcp->flags & TCB_BPTSET)) {
1770 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1771 return -1;
1772 }
1773 errno = 0;
1774 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1775 if (errno) {
1776 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1777 return -1;
1778 }
1779 tcp->flags &= ~TCB_BPTSET;
1780
1781#ifdef I386
1782 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1783 return -1;
1784 if (eip != tcp->baddr) {
1785 /* The breakpoint has not been reached yet. */
1786 if (debug)
1787 fprintf(stderr,
1788 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1789 eip, tcp->baddr);
1790 return 0;
1791 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001792#elif defined(X86_64)
1793 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1794 return -1;
1795 if (eip != tcp->baddr) {
1796 /* The breakpoint has not been reached yet. */
1797 if (debug)
1798 fprintf(stderr,
1799 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1800 eip, tcp->baddr);
1801 return 0;
1802 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001803#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001804 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001805 return -1;
1806 if (pc != tcp->baddr) {
1807 /* The breakpoint has not been reached yet. */
1808 if (debug)
1809 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1810 pc, tcp->baddr);
1811 return 0;
1812 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001813#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001814 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1815 return -1;
1816 if (pc != tcp->baddr) {
1817 /* The breakpoint has not been reached yet. */
1818 if (debug)
1819 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1820 pc, tcp->baddr);
1821 return 0;
1822 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001823#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001824 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1825 return -1;
1826 if (pc != tcp->baddr) {
1827 /* The breakpoint has not been reached yet. */
1828 if (debug)
1829 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1830 pc, tcp->baddr);
1831 return 0;
1832 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001833#elif defined(HPPA)
1834 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1835 return -1;
1836 iaoq &= ~0x03;
1837 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1838 /* The breakpoint has not been reached yet. */
1839 if (debug)
1840 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1841 iaoq, tcp->baddr);
1842 return 0;
1843 }
1844 iaoq = tcp->baddr | 3;
1845 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1846 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1847 * has no significant effect.
1848 */
1849 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1850 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001851#elif defined(SH)
1852 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1853 return -1;
1854 if (pc != tcp->baddr) {
1855 /* The breakpoint has not been reached yet. */
1856 if (debug)
1857 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1858 pc, tcp->baddr);
1859 return 0;
1860 }
1861
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001862#endif /* arch */
1863#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001864#endif /* LINUX */
1865
1866#ifdef SUNOS4
1867#ifdef SPARC
1868
1869#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001870 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001871#endif
1872
1873 if (!(tcp->flags & TCB_BPTSET)) {
1874 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1875 return -1;
1876 }
1877 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1878 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1879 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1880 return -1;
1881 }
1882 tcp->flags &= ~TCB_BPTSET;
1883
1884#if !LOOPA
1885 /*
1886 * Since we don't have a single instruction breakpoint, we may have
1887 * to adjust the program counter after removing the our `breakpoint'.
1888 */
1889 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1890 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1891 return -1;
1892 }
1893 if ((regs.r_pc < tcp->baddr) ||
1894 (regs.r_pc > tcp->baddr + 4)) {
1895 /* The breakpoint has not been reached yet */
1896 if (debug)
1897 fprintf(stderr,
1898 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1899 regs.r_pc, tcp->parent->baddr);
1900 return 0;
1901 }
1902 if (regs.r_pc != tcp->baddr)
1903 if (debug)
1904 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1905 regs.r_pc, tcp->baddr);
1906
1907 regs.r_pc = tcp->baddr;
1908 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1909 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1910 return -1;
1911 }
1912#endif /* LOOPA */
1913#endif /* SPARC */
1914#endif /* SUNOS4 */
1915
1916 return 0;
1917}
1918
Roland McGrathd81f1d92003-01-09 06:53:34 +00001919#endif
1920
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001921#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001922
1923#ifdef SUNOS4
1924
1925static int
1926getex(pid, hdr)
1927int pid;
1928struct exec *hdr;
1929{
1930 int n;
1931
1932 for (n = 0; n < sizeof *hdr; n += 4) {
1933 long res;
1934 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1935 return -1;
1936 memcpy(((char *) hdr) + n, &res, 4);
1937 }
1938 if (debug) {
1939 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1940 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1941 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1942 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1943 }
1944 return 0;
1945}
1946
1947int
1948fixvfork(tcp)
1949struct tcb *tcp;
1950{
1951 int pid = tcp->pid;
1952 /*
1953 * Change `vfork' in a freshly exec'ed dynamically linked
1954 * executable's (internal) symbol table to plain old `fork'
1955 */
1956
1957 struct exec hdr;
1958 struct link_dynamic dyn;
1959 struct link_dynamic_2 ld;
1960 char *strtab, *cp;
1961
1962 if (getex(pid, &hdr) < 0)
1963 return -1;
1964 if (!hdr.a_dynamic)
1965 return -1;
1966
1967 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1968 fprintf(stderr, "Cannot read DYNAMIC\n");
1969 return -1;
1970 }
1971 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1972 fprintf(stderr, "Cannot read link_dynamic_2\n");
1973 return -1;
1974 }
1975 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1976 fprintf(stderr, "fixvfork: out of memory\n");
1977 return -1;
1978 }
1979 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1980 (int)ld.ld_symb_size, strtab) < 0)
1981 goto err;
1982
1983#if 0
1984 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1985 fprintf(stderr, "[symbol: %s]\n", cp);
1986 cp += strlen(cp)+1;
1987 }
1988 return 0;
1989#endif
1990 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1991 if (strcmp(cp, "_vfork") == 0) {
1992 if (debug)
1993 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1994 strcpy(cp, "_fork");
1995 break;
1996 }
1997 cp += strlen(cp)+1;
1998 }
1999 if (cp < strtab + ld.ld_symb_size)
2000 /*
2001 * Write entire symbol table back to avoid
2002 * memory alignment bugs in ptrace
2003 */
2004 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2005 (int)ld.ld_symb_size, strtab) < 0)
2006 goto err;
2007
2008 free(strtab);
2009 return 0;
2010
2011err:
2012 free(strtab);
2013 return -1;
2014}
2015
2016#endif /* SUNOS4 */