blob: 7dcc5b3b134e4d00b0ee17957ef3a3633d849913 [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
1157typedef unsigned long *arg_setup_state;
1158
1159static int
1160arg_setup(struct tcb *tcp, arg_setup_state *state)
1161{
1162 unsigned long *bsp, cfm, sof, sol;
1163
1164 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1165 return -1;
1166 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1167 return -1;
1168
1169 sof = (cfm >> 0) & 0x7f;
1170 sol = (cfm >> 7) & 0x7f;
1171 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1172
1173 *state = bsp;
1174 return 0;
1175}
1176
1177# define arg_finish_change(tcp, state) 0
1178
1179#ifdef SYS_fork
1180static int
1181get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1182{
1183 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
1184 sizeof(long), (void *) valp);
1185}
1186
1187static int
1188get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1189{
1190 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
1191 sizeof(long), (void *) valp);
1192}
1193#endif
1194
1195static int
1196set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1197{
1198 unsigned long *ap;
1199 ap = ia64_rse_skip_regs(*state, 0);
1200 errno = 0;
1201 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1202 return errno ? -1 : 0;
1203}
1204
1205static int
1206set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1207{
1208 unsigned long *ap;
1209 ap = ia64_rse_skip_regs(*state, 1);
1210 errno = 0;
1211 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1212 return errno ? -1 : 0;
1213}
1214
1215#elif defined (SPARC)
1216
1217typedef struct regs arg_setup_state;
1218
1219# define arg_setup(tcp, state) \
1220 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1221# define arg_finish_change(tcp, state) \
1222 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1223
1224# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1225# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1226# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1227# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001228# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001229
1230#else
1231
1232# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001233/* Note: this is only true for the `clone' system call, which handles
1234 arguments specially. We could as well say that its first two arguments
1235 are swapped relative to other architectures, but that would just be
1236 another #ifdef in the calls. */
1237# define arg0_offset PT_GPR3
1238# define arg1_offset PT_ORIGGPR2
1239# define restore_arg0(tcp, state, val) ((void) (state), 0)
1240# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001241# elif defined (ALPHA) || defined (MIPS)
1242# define arg0_offset REG_A0
1243# define arg1_offset (REG_A0+1)
1244# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001245# define arg0_offset (sizeof(unsigned long)*PT_R3)
1246# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001247# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001248# elif defined (HPPA)
1249# define arg0_offset PT_GR26
1250# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001251# elif defined (X86_64)
1252# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1253# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathac971c22003-03-31 01:03:33 +00001254# elif defined (SH)
1255# define arg0_offset (4*(REG_REG0+4))
1256# define arg1_offset (4*(REG_REG0+5))
Roland McGrathf5a47772003-06-26 22:40:42 +00001257# elif defined (SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001258 /* ABI defines arg0 & 1 in r2 & r3 */
1259# define arg0_offset (REG_OFFSET+16)
1260# define arg1_offset (REG_OFFSET+24)
1261# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001262# else
1263# define arg0_offset 0
1264# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001265# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001266# define restore_arg0(tcp, state, val) 0
1267# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001268# endif
1269
1270typedef int arg_setup_state;
1271
1272# define arg_setup(tcp, state) (0)
1273# define arg_finish_change(tcp, state) 0
1274# define get_arg0(tcp, cookie, valp) \
1275 (upeek ((tcp)->pid, arg0_offset, (valp)))
1276# define get_arg1(tcp, cookie, valp) \
1277 (upeek ((tcp)->pid, arg1_offset, (valp)))
1278
1279static int
1280set_arg0 (struct tcb *tcp, void *cookie, long val)
1281{
1282 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1283}
1284
1285static int
1286set_arg1 (struct tcb *tcp, void *cookie, long val)
1287{
1288 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1289}
1290
1291#endif
1292
Roland McGrathe1df47f2003-01-14 09:46:15 +00001293#ifndef restore_arg0
1294# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1295#endif
1296#ifndef restore_arg1
1297# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1298#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001299
1300int
1301setbpt(tcp)
1302struct tcb *tcp;
1303{
1304 extern int change_syscall(struct tcb *, int);
1305 arg_setup_state state;
1306
1307 if (tcp->flags & TCB_BPTSET) {
1308 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1309 return -1;
1310 }
1311
1312 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001313#ifdef SYS_vfork
1314 case SYS_vfork:
1315#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001316#ifdef SYS_fork
1317 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001318#endif
1319#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001320 if (arg_setup (tcp, &state) < 0
1321 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1322 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1323 || change_syscall(tcp, SYS_clone) < 0
1324 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1325 || set_arg1 (tcp, &state, 0) < 0
1326 || arg_finish_change (tcp, &state) < 0)
1327 return -1;
1328 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1329 tcp->u_arg[1] = 0;
1330 tcp->flags |= TCB_BPTSET;
1331 return 0;
1332#endif
1333
1334 case SYS_clone:
1335#ifdef SYS_clone2
1336 case SYS_clone2:
1337#endif
1338 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1339 && (arg_setup (tcp, &state) < 0
1340 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1341 || arg_finish_change (tcp, &state) < 0))
1342 return -1;
1343 tcp->flags |= TCB_BPTSET;
1344 tcp->inst[0] = tcp->u_arg[0];
1345 tcp->inst[1] = tcp->u_arg[1];
1346 return 0;
1347
1348 default:
1349 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1350 tcp->scno, tcp->pid);
1351 break;
1352 }
1353
1354 return -1;
1355}
1356
1357int
1358clearbpt(tcp)
1359struct tcb *tcp;
1360{
1361 arg_setup_state state;
1362 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001363 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1364 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001365 || arg_finish_change (tcp, &state))
1366 return -1;
1367 tcp->flags &= ~TCB_BPTSET;
1368 return 0;
1369}
1370
1371#else
1372
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001373int
1374setbpt(tcp)
1375struct tcb *tcp;
1376{
1377
1378#ifdef LINUX
1379#ifdef SPARC
1380 /* We simply use the SunOS breakpoint code. */
1381
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001382 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001383#define LOOPA 0x30800000 /* ba,a 0 */
1384
1385 if (tcp->flags & TCB_BPTSET) {
1386 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1387 return -1;
1388 }
1389 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1390 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1391 return -1;
1392 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001393 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001394 errno = 0;
1395 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1396 if(errno) {
1397 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1398 return -1;
1399 }
1400
1401 /*
1402 * XXX - BRUTAL MODE ON
1403 * We cannot set a real BPT in the child, since it will not be
1404 * traced at the moment it will reach the trap and would probably
1405 * die with a core dump.
1406 * Thus, we are force our way in by taking out two instructions
1407 * and insert an eternal loop instead, in expectance of the SIGSTOP
1408 * generated by out PTRACE_ATTACH.
1409 * Of cause, if we evaporate ourselves in the middle of all this...
1410 */
1411 errno = 0;
1412 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1413 if(errno) {
1414 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1415 return -1;
1416 }
1417 tcp->flags |= TCB_BPTSET;
1418
1419#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001420#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001421 if (ia32) {
1422# define LOOP 0x0000feeb
1423 if (tcp->flags & TCB_BPTSET) {
1424 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1425 tcp->pid);
1426 return -1;
1427 }
1428 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1429 return -1;
1430 if (debug)
1431 fprintf(stderr, "[%d] setting bpt at %lx\n",
1432 tcp->pid, tcp->baddr);
1433 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1434 (char *) tcp->baddr, 0);
1435 if (errno) {
1436 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1437 return -1;
1438 }
1439 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1440 if (errno) {
1441 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1442 return -1;
1443 }
1444 tcp->flags |= TCB_BPTSET;
1445 } else {
1446 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001447 * Our strategy here is to replace the bundle that
1448 * contained the clone() syscall with a bundle of the
1449 * form:
1450 *
1451 * { 1: br 1b; br 1b; br 1b }
1452 *
1453 * This ensures that the newly forked child will loop
1454 * endlessly until we've got a chance to attach to it.
1455 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001456# define LOOP0 0x0000100000000017
1457# define LOOP1 0x4000000000200000
1458 unsigned long addr, ipsr;
1459 pid_t pid;
1460
1461 pid = tcp->pid;
1462 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1463 return -1;
1464 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1465 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001466 /* store "ri" in low two bits */
1467 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001468
1469 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001470 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1471 0);
1472 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1473 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001474 if (errno) {
1475 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1476 return -1;
1477 }
1478
1479 errno = 0;
1480 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1481 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1482 if (errno) {
1483 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1484 return -1;
1485 }
1486 tcp->flags |= TCB_BPTSET;
1487 }
1488#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489
Michal Ludvig0e035502002-09-23 15:41:01 +00001490#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001491#define LOOP 0x0000feeb
1492#elif defined (M68K)
1493#define LOOP 0x60fe0000
1494#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001495#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001496#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001497#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001499#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001500#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001501#define LOOP 0x1000ffff
1502#elif defined(S390)
1503#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001504#elif defined(S390X)
1505#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001506#elif defined(HPPA)
1507#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001508#elif defined(SH)
1509#ifdef __LITTLE_ENDIAN__
1510#define LOOP 0x0000affe
1511#else
1512#define LOOP 0xfeaf0000
1513#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001514#else
1515#error unknown architecture
1516#endif
1517
1518 if (tcp->flags & TCB_BPTSET) {
1519 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1520 return -1;
1521 }
1522#if defined (I386)
1523 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1524 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001525#elif defined (X86_64)
1526 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1527 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528#elif defined (M68K)
1529 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1530 return -1;
1531#elif defined (ALPHA)
1532 return -1;
1533#elif defined (ARM)
1534 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001535#elif defined (MIPS)
1536 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001537#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001538 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001540#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001541 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1542 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001543#elif defined(HPPA)
1544 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1545 return -1;
1546 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001547#elif defined(SH)
1548 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1549 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001550#else
1551#error unknown architecture
1552#endif
1553 if (debug)
1554 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1555 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1556 if (errno) {
1557 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1558 return -1;
1559 }
1560 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1561 if (errno) {
1562 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1563 return -1;
1564 }
1565 tcp->flags |= TCB_BPTSET;
1566
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001567#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001568#endif /* SPARC */
1569#endif /* LINUX */
1570
1571#ifdef SUNOS4
1572#ifdef SPARC /* This code is slightly sparc specific */
1573
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001574 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001575#define BPT 0x91d02001 /* ta 1 */
1576#define LOOP 0x10800000 /* ba 0 */
1577#define LOOPA 0x30800000 /* ba,a 0 */
1578#define NOP 0x01000000
1579#if LOOPA
1580 static int loopdeloop[1] = {LOOPA};
1581#else
1582 static int loopdeloop[2] = {LOOP, NOP};
1583#endif
1584
1585 if (tcp->flags & TCB_BPTSET) {
1586 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1587 return -1;
1588 }
1589 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1590 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1591 return -1;
1592 }
1593 tcp->baddr = regs.r_o7 + 8;
1594 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1595 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1596 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1597 return -1;
1598 }
1599
1600 /*
1601 * XXX - BRUTAL MODE ON
1602 * We cannot set a real BPT in the child, since it will not be
1603 * traced at the moment it will reach the trap and would probably
1604 * die with a core dump.
1605 * Thus, we are force our way in by taking out two instructions
1606 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1607 * generated by out PTRACE_ATTACH.
1608 * Of cause, if we evaporate ourselves in the middle of all this...
1609 */
1610 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1611 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1612 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1613 return -1;
1614 }
1615 tcp->flags |= TCB_BPTSET;
1616
1617#endif /* SPARC */
1618#endif /* SUNOS4 */
1619
1620 return 0;
1621}
1622
1623int
1624clearbpt(tcp)
1625struct tcb *tcp;
1626{
1627
1628#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001629#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001631#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001632 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001633#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001634 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001635#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001636 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001637#elif defined(HPPA)
1638 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001639#elif defined(SH)
1640 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001641#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642
1643#ifdef SPARC
1644 /* Again, we borrow the SunOS breakpoint code. */
1645 if (!(tcp->flags & TCB_BPTSET)) {
1646 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1647 return -1;
1648 }
1649 errno = 0;
1650 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1651 if(errno) {
1652 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1653 return -1;
1654 }
1655 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001656#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001657 if (ia32) {
1658 unsigned long addr;
1659
1660 if (debug)
1661 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1662 if (!(tcp->flags & TCB_BPTSET)) {
1663 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1664 return -1;
1665 }
1666 errno = 0;
1667 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1668 if (errno) {
1669 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1670 return -1;
1671 }
1672 tcp->flags &= ~TCB_BPTSET;
1673
1674 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1675 return -1;
1676 if (addr != tcp->baddr) {
1677 /* The breakpoint has not been reached yet. */
1678 if (debug)
1679 fprintf(stderr,
1680 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1681 addr, tcp->baddr);
1682 return 0;
1683 }
1684 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001685 unsigned long addr, ipsr;
1686 pid_t pid;
1687
1688 pid = tcp->pid;
1689
1690 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1691 return -1;
1692 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1693 return -1;
1694
1695 /* restore original bundle: */
1696 errno = 0;
1697 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1698 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1699 if (errno) {
1700 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1701 return -1;
1702 }
1703
1704 /* restore original "ri" in ipsr: */
1705 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1706 errno = 0;
1707 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1708 if (errno) {
1709 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1710 return -1;
1711 }
1712
1713 tcp->flags &= ~TCB_BPTSET;
1714
1715 if (addr != (tcp->baddr & ~0x3)) {
1716 /* the breakpoint has not been reached yet. */
1717 if (debug)
1718 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1719 addr, tcp->baddr);
1720 return 0;
1721 }
1722 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001723#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001724
1725 if (debug)
1726 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1727 if (!(tcp->flags & TCB_BPTSET)) {
1728 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1729 return -1;
1730 }
1731 errno = 0;
1732 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1733 if (errno) {
1734 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1735 return -1;
1736 }
1737 tcp->flags &= ~TCB_BPTSET;
1738
1739#ifdef I386
1740 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1741 return -1;
1742 if (eip != tcp->baddr) {
1743 /* The breakpoint has not been reached yet. */
1744 if (debug)
1745 fprintf(stderr,
1746 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1747 eip, tcp->baddr);
1748 return 0;
1749 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001750#elif defined(X86_64)
1751 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1752 return -1;
1753 if (eip != tcp->baddr) {
1754 /* The breakpoint has not been reached yet. */
1755 if (debug)
1756 fprintf(stderr,
1757 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1758 eip, tcp->baddr);
1759 return 0;
1760 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001761#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001762 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001763 return -1;
1764 if (pc != tcp->baddr) {
1765 /* The breakpoint has not been reached yet. */
1766 if (debug)
1767 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1768 pc, tcp->baddr);
1769 return 0;
1770 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001771#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1773 return -1;
1774 if (pc != tcp->baddr) {
1775 /* The breakpoint has not been reached yet. */
1776 if (debug)
1777 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1778 pc, tcp->baddr);
1779 return 0;
1780 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001781#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1783 return -1;
1784 if (pc != tcp->baddr) {
1785 /* The breakpoint has not been reached yet. */
1786 if (debug)
1787 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1788 pc, tcp->baddr);
1789 return 0;
1790 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001791#elif defined(HPPA)
1792 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1793 return -1;
1794 iaoq &= ~0x03;
1795 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1796 /* The breakpoint has not been reached yet. */
1797 if (debug)
1798 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1799 iaoq, tcp->baddr);
1800 return 0;
1801 }
1802 iaoq = tcp->baddr | 3;
1803 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1804 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1805 * has no significant effect.
1806 */
1807 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1808 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001809#elif defined(SH)
1810 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1811 return -1;
1812 if (pc != tcp->baddr) {
1813 /* The breakpoint has not been reached yet. */
1814 if (debug)
1815 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1816 pc, tcp->baddr);
1817 return 0;
1818 }
1819
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001820#endif /* arch */
1821#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001822#endif /* LINUX */
1823
1824#ifdef SUNOS4
1825#ifdef SPARC
1826
1827#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001828 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001829#endif
1830
1831 if (!(tcp->flags & TCB_BPTSET)) {
1832 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1833 return -1;
1834 }
1835 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1836 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1837 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1838 return -1;
1839 }
1840 tcp->flags &= ~TCB_BPTSET;
1841
1842#if !LOOPA
1843 /*
1844 * Since we don't have a single instruction breakpoint, we may have
1845 * to adjust the program counter after removing the our `breakpoint'.
1846 */
1847 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1848 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1849 return -1;
1850 }
1851 if ((regs.r_pc < tcp->baddr) ||
1852 (regs.r_pc > tcp->baddr + 4)) {
1853 /* The breakpoint has not been reached yet */
1854 if (debug)
1855 fprintf(stderr,
1856 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1857 regs.r_pc, tcp->parent->baddr);
1858 return 0;
1859 }
1860 if (regs.r_pc != tcp->baddr)
1861 if (debug)
1862 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1863 regs.r_pc, tcp->baddr);
1864
1865 regs.r_pc = tcp->baddr;
1866 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1867 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1868 return -1;
1869 }
1870#endif /* LOOPA */
1871#endif /* SPARC */
1872#endif /* SUNOS4 */
1873
1874 return 0;
1875}
1876
Roland McGrathd81f1d92003-01-09 06:53:34 +00001877#endif
1878
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001879#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001880
1881#ifdef SUNOS4
1882
1883static int
1884getex(pid, hdr)
1885int pid;
1886struct exec *hdr;
1887{
1888 int n;
1889
1890 for (n = 0; n < sizeof *hdr; n += 4) {
1891 long res;
1892 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1893 return -1;
1894 memcpy(((char *) hdr) + n, &res, 4);
1895 }
1896 if (debug) {
1897 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1898 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1899 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1900 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1901 }
1902 return 0;
1903}
1904
1905int
1906fixvfork(tcp)
1907struct tcb *tcp;
1908{
1909 int pid = tcp->pid;
1910 /*
1911 * Change `vfork' in a freshly exec'ed dynamically linked
1912 * executable's (internal) symbol table to plain old `fork'
1913 */
1914
1915 struct exec hdr;
1916 struct link_dynamic dyn;
1917 struct link_dynamic_2 ld;
1918 char *strtab, *cp;
1919
1920 if (getex(pid, &hdr) < 0)
1921 return -1;
1922 if (!hdr.a_dynamic)
1923 return -1;
1924
1925 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1926 fprintf(stderr, "Cannot read DYNAMIC\n");
1927 return -1;
1928 }
1929 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1930 fprintf(stderr, "Cannot read link_dynamic_2\n");
1931 return -1;
1932 }
1933 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1934 fprintf(stderr, "fixvfork: out of memory\n");
1935 return -1;
1936 }
1937 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1938 (int)ld.ld_symb_size, strtab) < 0)
1939 goto err;
1940
1941#if 0
1942 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1943 fprintf(stderr, "[symbol: %s]\n", cp);
1944 cp += strlen(cp)+1;
1945 }
1946 return 0;
1947#endif
1948 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1949 if (strcmp(cp, "_vfork") == 0) {
1950 if (debug)
1951 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1952 strcpy(cp, "_fork");
1953 break;
1954 }
1955 cp += strlen(cp)+1;
1956 }
1957 if (cp < strtab + ld.ld_symb_size)
1958 /*
1959 * Write entire symbol table back to avoid
1960 * memory alignment bugs in ptrace
1961 */
1962 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1963 (int)ld.ld_symb_size, strtab) < 0)
1964 goto err;
1965
1966 free(strtab);
1967 return 0;
1968
1969err:
1970 free(strtab);
1971 return -1;
1972}
1973
1974#endif /* SUNOS4 */