blob: d01b1d84c398fb86ed880b6128076df2f2d34d70 [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
75#include <asm/reg.h>
76
77#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000078
79#include <linux/unistd.h>
80
81#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
82 type5,arg5,syscall) \
83type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
84{ \
85 long __res; \
86\
87__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
88 "or %%g0, %2, %%o1\n\t" \
89 "or %%g0, %3, %%o2\n\t" \
90 "or %%g0, %4, %%o3\n\t" \
91 "or %%g0, %5, %%o4\n\t" \
92 "or %%g0, %6, %%g1\n\t" \
93 "t 0x10\n\t" \
94 "bcc 1f\n\t" \
95 "or %%g0, %%o0, %0\n\t" \
96 "sub %%g0, %%o0, %0\n\t" \
97 "1:\n\t" \
98 : "=r" (__res) \
99 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
100 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
101 "i" (__NR_##syscall) \
102 : "g1", "o0", "o1", "o2", "o3", "o4"); \
103if (__res>=0) \
104 return (type) __res; \
105errno = -__res; \
106return -1; \
107}
108
109static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
110
111#define _ptrace
112
113#endif
114
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000115#endif
116
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117/* macros */
118#ifndef MAX
119#define MAX(a,b) (((a) > (b)) ? (a) : (b))
120#endif
121#ifndef MIN
122#define MIN(a,b) (((a) < (b)) ? (a) : (b))
123#endif
124
125void
126tv_tv(tv, a, b)
127struct timeval *tv;
128int a;
129int b;
130{
131 tv->tv_sec = a;
132 tv->tv_usec = b;
133}
134
135int
136tv_nz(a)
137struct timeval *a;
138{
139 return a->tv_sec || a->tv_usec;
140}
141
142int
143tv_cmp(a, b)
144struct timeval *a, *b;
145{
146 if (a->tv_sec < b->tv_sec
147 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
148 return -1;
149 if (a->tv_sec > b->tv_sec
150 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
151 return 1;
152 return 0;
153}
154
155double
156tv_float(tv)
157struct timeval *tv;
158{
159 return tv->tv_sec + tv->tv_usec/1000000.0;
160}
161
162void
163tv_add(tv, a, b)
164struct timeval *tv, *a, *b;
165{
166 tv->tv_sec = a->tv_sec + b->tv_sec;
167 tv->tv_usec = a->tv_usec + b->tv_usec;
168 if (tv->tv_usec > 1000000) {
169 tv->tv_sec++;
170 tv->tv_usec -= 1000000;
171 }
172}
173
174void
175tv_sub(tv, a, b)
176struct timeval *tv, *a, *b;
177{
178 tv->tv_sec = a->tv_sec - b->tv_sec;
179 tv->tv_usec = a->tv_usec - b->tv_usec;
180 if (((long) tv->tv_usec) < 0) {
181 tv->tv_sec--;
182 tv->tv_usec += 1000000;
183 }
184}
185
186void
187tv_div(tv, a, n)
188struct timeval *tv, *a;
189int n;
190{
191 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
192 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
193 tv->tv_usec %= 1000000;
194}
195
196void
197tv_mul(tv, a, n)
198struct timeval *tv, *a;
199int n;
200{
201 tv->tv_usec = a->tv_usec * n;
202 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
203 tv->tv_usec %= 1000000;
204}
205
206char *
207xlookup(xlat, val)
208struct xlat *xlat;
209int val;
210{
211 for (; xlat->str != NULL; xlat++)
212 if (xlat->val == val)
213 return xlat->str;
214 return NULL;
215}
216
217/*
218 * Print entry in struct xlat table, if there.
219 */
220void
221printxval(xlat, val, dflt)
222struct xlat *xlat;
223int val;
224char *dflt;
225{
226 char *str = xlookup(xlat, val);
227
228 if (str)
229 tprintf("%s", str);
230 else
231 tprintf("%#x /* %s */", val, dflt);
232}
233
234/*
235 * Interpret `xlat' as an array of flags
236 * print the entries whose bits are on in `flags'
237 * return # of flags printed.
238 */
239int
240addflags(xlat, flags)
241struct xlat *xlat;
242int flags;
243{
244 int n;
245
246 for (n = 0; xlat->str; xlat++) {
247 if (xlat->val && (flags & xlat->val) == xlat->val) {
248 tprintf("|%s", xlat->str);
249 flags &= ~xlat->val;
250 n++;
251 }
252 }
253 if (flags) {
254 tprintf("|%#x", flags);
255 n++;
256 }
257 return n;
258}
259
260int
261printflags(xlat, flags)
262struct xlat *xlat;
263int flags;
264{
265 int n;
266 char *sep;
267
268 if (flags == 0 && xlat->val == 0) {
269 tprintf("%s", xlat->str);
270 return 1;
271 }
272
273 sep = "";
274 for (n = 0; xlat->str; xlat++) {
275 if (xlat->val && (flags & xlat->val) == xlat->val) {
276 tprintf("%s%s", sep, xlat->str);
277 flags &= ~xlat->val;
278 sep = "|";
279 n++;
280 }
281 }
282 if (flags) {
283 tprintf("%s%#x", sep, flags);
284 n++;
285 }
286 return n;
287}
288
289void
290printnum(tcp, addr, fmt)
291struct tcb *tcp;
292long addr;
293char *fmt;
294{
Roland McGratheb285352003-01-14 09:59:00 +0000295 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000296
297 if (!addr) {
298 tprintf("NULL");
299 return;
300 }
301 if (umove(tcp, addr, &num) < 0) {
302 tprintf("%#lx", addr);
303 return;
304 }
305 tprintf("[");
306 tprintf(fmt, num);
307 tprintf("]");
308}
309
310static char path[MAXPATHLEN + 1];
311
312void
313string_quote(str)
314char *str;
315{
316 char buf[2 * MAXPATHLEN + 1];
317 char *s;
318
319 if (!strpbrk(str, "\"\'\\")) {
320 tprintf("\"%s\"", str);
321 return;
322 }
323 for (s = buf; *str; str++) {
324 switch (*str) {
325 case '\"': case '\'': case '\\':
326 *s++ = '\\'; *s++ = *str; break;
327 default:
328 *s++ = *str; break;
329 }
330 }
331 *s = '\0';
332 tprintf("\"%s\"", buf);
333}
334
335void
336printpath(tcp, addr)
337struct tcb *tcp;
338long addr;
339{
340 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
341 tprintf("%#lx", addr);
342 else
343 string_quote(path);
344 return;
345}
346
347void
348printpathn(tcp, addr, n)
349struct tcb *tcp;
350long addr;
351int n;
352{
353 if (umovestr(tcp, addr, n, path) < 0)
354 tprintf("%#lx", addr);
355 else {
356 path[n] = '\0';
357 string_quote(path);
358 }
359}
360
361void
362printstr(tcp, addr, len)
363struct tcb *tcp;
364long addr;
365int len;
366{
367 static unsigned char *str = NULL;
368 static char *outstr;
369 int i, n, c, usehex;
370 char *s, *outend;
371
372 if (!addr) {
373 tprintf("NULL");
374 return;
375 }
376 if (!str) {
377 if ((str = malloc(max_strlen)) == NULL
378 || (outstr = malloc(2*max_strlen)) == NULL) {
379 fprintf(stderr, "printstr: no memory\n");
380 tprintf("%#lx", addr);
381 return;
382 }
383 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000384 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385 if (len < 0) {
386 n = max_strlen;
387 if (umovestr(tcp, addr, n, (char *) str) < 0) {
388 tprintf("%#lx", addr);
389 return;
390 }
391 }
392 else {
393 n = MIN(len, max_strlen);
394 if (umoven(tcp, addr, n, (char *) str) < 0) {
395 tprintf("%#lx", addr);
396 return;
397 }
398 }
399
400 usehex = 0;
401 if (xflag > 1)
402 usehex = 1;
403 else if (xflag) {
404 for (i = 0; i < n; i++) {
405 c = str[i];
406 if (len < 0 && c == '\0')
407 break;
408 if (!isprint(c) && !isspace(c)) {
409 usehex = 1;
410 break;
411 }
412 }
413 }
414
415 s = outstr;
416 *s++ = '\"';
417
418 if (usehex) {
419 for (i = 0; i < n; i++) {
420 c = str[i];
421 if (len < 0 && c == '\0')
422 break;
423 sprintf(s, "\\x%02x", c);
424 s += 4;
425 if (s > outend)
426 break;
427 }
428 }
429 else {
430 for (i = 0; i < n; i++) {
431 c = str[i];
432 if (len < 0 && c == '\0')
433 break;
434 switch (c) {
435 case '\"': case '\'': case '\\':
436 *s++ = '\\'; *s++ = c; break;
437 case '\f':
438 *s++ = '\\'; *s++ = 'f'; break;
439 case '\n':
440 *s++ = '\\'; *s++ = 'n'; break;
441 case '\r':
442 *s++ = '\\'; *s++ = 'r'; break;
443 case '\t':
444 *s++ = '\\'; *s++ = 't'; break;
445 case '\v':
446 *s++ = '\\'; *s++ = 'v'; break;
447 default:
448 if (isprint(c))
449 *s++ = c;
450 else if (i < n - 1 && isdigit(str[i + 1])) {
451 sprintf(s, "\\%03o", c);
452 s += 4;
453 }
454 else {
455 sprintf(s, "\\%o", c);
456 s += strlen(s);
457 }
458 break;
459 }
460 if (s > outend)
461 break;
462 }
463 }
464
465 *s++ = '\"';
466 if (i < len || (len < 0 && (i == n || s > outend))) {
467 *s++ = '.'; *s++ = '.'; *s++ = '.';
468 }
469 *s = '\0';
470 tprintf("%s", outstr);
471}
472
John Hughes1d08dcf2001-07-10 13:48:44 +0000473#if HAVE_SYS_UIO_H
474void
475dumpiov(tcp, len, addr)
476struct tcb * tcp;
477int len;
478long addr;
479{
480 struct iovec *iov;
481 int i;
482
Roland McGrath1e85cf92002-12-16 20:40:54 +0000483
John Hughes1d08dcf2001-07-10 13:48:44 +0000484 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
485 fprintf(stderr, "dump: No memory");
486 return;
487 }
488 if (umoven(tcp, addr,
489 len * sizeof *iov, (char *) iov) >= 0) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000490
John Hughes1d08dcf2001-07-10 13:48:44 +0000491 for (i = 0; i < len; i++) {
492 /* include the buffer number to make it easy to
493 * match up the trace with the source */
494 tprintf(" * %lu bytes in buffer %d\n",
495 (unsigned long)iov[i].iov_len, i);
496 dumpstr(tcp, (long) iov[i].iov_base,
497 iov[i].iov_len);
498 }
499 }
500 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000501
John Hughes1d08dcf2001-07-10 13:48:44 +0000502}
503#endif
504
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505void
506dumpstr(tcp, addr, len)
507struct tcb *tcp;
508long addr;
509int len;
510{
511 static int strsize = -1;
512 static unsigned char *str;
513 static char outstr[80];
514 char *s;
515 int i, j;
516
517 if (strsize < len) {
518 if (str)
519 free(str);
520 if ((str = malloc(len)) == NULL) {
521 fprintf(stderr, "dump: no memory\n");
522 return;
523 }
524 strsize = len;
525 }
526
527 if (umoven(tcp, addr, len, (char *) str) < 0)
528 return;
529
530 for (i = 0; i < len; i += 16) {
531 s = outstr;
532 sprintf(s, " | %05x ", i);
533 s += 9;
534 for (j = 0; j < 16; j++) {
535 if (j == 8)
536 *s++ = ' ';
537 if (i + j < len) {
538 sprintf(s, " %02x", str[i + j]);
539 s += 3;
540 }
541 else {
542 *s++ = ' '; *s++ = ' '; *s++ = ' ';
543 }
544 }
545 *s++ = ' '; *s++ = ' ';
546 for (j = 0; j < 16; j++) {
547 if (j == 8)
548 *s++ = ' ';
549 if (i + j < len) {
550 if (isprint(str[i + j]))
551 *s++ = str[i + j];
552 else
553 *s++ = '.';
554 }
555 else
556 *s++ = ' ';
557 }
558 tprintf("%s |\n", outstr);
559 }
560}
561
562#define PAGMASK (~(PAGSIZ - 1))
563/*
564 * move `len' bytes of data from process `pid'
565 * at address `addr' to our space at `laddr'
566 */
567int
568umoven(tcp, addr, len, laddr)
569struct tcb *tcp;
570long addr;
571int len;
572char *laddr;
573{
574
575#ifdef LINUX
576 int pid = tcp->pid;
577 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000578 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000579 union {
580 long val;
581 char x[sizeof(long)];
582 } u;
583
584 if (addr & (sizeof(long) - 1)) {
585 /* addr not a multiple of sizeof(long) */
586 n = addr - (addr & -sizeof(long)); /* residue */
587 addr &= -sizeof(long); /* residue */
588 errno = 0;
589 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
590 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000591 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000592 /* Ran into 'end of memory' - stupid "printpath" */
593 return 0;
594 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000595 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596 perror("ptrace: umoven");
597 return -1;
598 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000599 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000600 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
601 addr += sizeof(long), laddr += m, len -= m;
602 }
603 while (len) {
604 errno = 0;
605 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
606 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000607 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000608 /* Ran into 'end of memory' - stupid "printpath" */
609 return 0;
610 }
611 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, m = MIN(sizeof(long), len));
616 addr += sizeof(long), laddr += m, len -= m;
617 }
618#endif /* LINUX */
619
620#ifdef SUNOS4
621 int pid = tcp->pid;
622#if 0
623 int n, m;
624 union {
625 long val;
626 char x[sizeof(long)];
627 } u;
628
629 if (addr & (sizeof(long) - 1)) {
630 /* addr not a multiple of sizeof(long) */
631 n = addr - (addr & -sizeof(long)); /* residue */
632 addr &= -sizeof(long); /* residue */
633 errno = 0;
634 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
635 if (errno) {
636 perror("umoven");
637 return -1;
638 }
639 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
640 addr += sizeof(long), laddr += m, len -= m;
641 }
642 while (len) {
643 errno = 0;
644 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
645 if (errno) {
646 perror("umoven");
647 return -1;
648 }
649 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
650 addr += sizeof(long), laddr += m, len -= m;
651 }
652#else /* !oldway */
653 int n;
654
655 while (len) {
656 n = MIN(len, PAGSIZ);
657 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
658 if (ptrace(PTRACE_READDATA, pid,
659 (char *) addr, len, laddr) < 0) {
660 perror("umoven: ptrace(PTRACE_READDATA, ...)");
661 abort();
662 return -1;
663 }
664 len -= n;
665 addr += n;
666 laddr += n;
667 }
668#endif /* !oldway */
669#endif /* SUNOS4 */
670
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000671#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000672#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000673 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000674#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000675 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000677 lseek(fd, addr, SEEK_SET);
678 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000679 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000680#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000681
682 return 0;
683}
684
685/*
686 * like `umove' but make the additional effort of looking
687 * for a terminating zero byte.
688 */
689int
690umovestr(tcp, addr, len, laddr)
691struct tcb *tcp;
692long addr;
693int len;
694char *laddr;
695{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000696#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000697#ifdef HAVE_MP_PROCFS
698 int fd = tcp->pfd_as;
699#else
700 int fd = tcp->pfd;
701#endif
702 /* Some systems (e.g. FreeBSD) can be upset if we read off the
703 end of valid memory, avoid this by trying to read up
704 to page boundaries. But we don't know what a page is (and
705 getpagesize(2) (if it exists) doesn't necessarily return
706 hardware page size). Assume all pages >= 1024 (a-historical
707 I know) */
708
709 int page = 1024; /* How to find this? */
710 int move = page - (addr & (page - 1));
711 int left = len;
712
713 lseek(fd, addr, SEEK_SET);
714
715 while (left) {
716 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000717 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000718 return left != len ? 0 : -1;
719 if (memchr (laddr, 0, move)) break;
720 left -= move;
721 laddr += move;
722 addr += move;
723 move = page;
724 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000725#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000726 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000727 int pid = tcp->pid;
728 int i, n, m;
729 union {
730 long val;
731 char x[sizeof(long)];
732 } u;
733
734 if (addr & (sizeof(long) - 1)) {
735 /* addr not a multiple of sizeof(long) */
736 n = addr - (addr & -sizeof(long)); /* residue */
737 addr &= -sizeof(long); /* residue */
738 errno = 0;
739 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
740 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000741 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000742 /* Ran into 'end of memory' - stupid "printpath" */
743 return 0;
744 }
745 perror("umovestr");
746 return -1;
747 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000748 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000749 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
750 while (n & (sizeof(long) - 1))
751 if (u.x[n++] == '\0')
752 return 0;
753 addr += sizeof(long), laddr += m, len -= m;
754 }
755 while (len) {
756 errno = 0;
757 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
758 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000759 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 /* Ran into 'end of memory' - stupid "printpath" */
761 return 0;
762 }
763 perror("umovestr");
764 return -1;
765 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000766 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
768 for (i = 0; i < sizeof(long); i++)
769 if (u.x[i] == '\0')
770 return 0;
771
772 addr += sizeof(long), laddr += m, len -= m;
773 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000774#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000775 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000776}
777
778#ifdef LINUX
779#ifndef SPARC
780#define PTRACE_WRITETEXT 101
781#define PTRACE_WRITEDATA 102
782#endif /* !SPARC */
783#endif /* LINUX */
784
785#ifdef SUNOS4
786
787static int
788uload(cmd, pid, addr, len, laddr)
789int cmd;
790int pid;
791long addr;
792int len;
793char *laddr;
794{
795#if 0
796 int n;
797
798 while (len) {
799 n = MIN(len, PAGSIZ);
800 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
801 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
802 perror("uload: ptrace(PTRACE_WRITE, ...)");
803 return -1;
804 }
805 len -= n;
806 addr += n;
807 laddr += n;
808 }
809#else
810 int peek, poke;
811 int n, m;
812 union {
813 long val;
814 char x[sizeof(long)];
815 } u;
816
817 if (cmd == PTRACE_WRITETEXT) {
818 peek = PTRACE_PEEKTEXT;
819 poke = PTRACE_POKETEXT;
820 }
821 else {
822 peek = PTRACE_PEEKDATA;
823 poke = PTRACE_POKEDATA;
824 }
825 if (addr & (sizeof(long) - 1)) {
826 /* addr not a multiple of sizeof(long) */
827 n = addr - (addr & -sizeof(long)); /* residue */
828 addr &= -sizeof(long);
829 errno = 0;
830 u.val = ptrace(peek, pid, (char *) addr, 0);
831 if (errno) {
832 perror("uload: POKE");
833 return -1;
834 }
835 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
836 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
837 perror("uload: POKE");
838 return -1;
839 }
840 addr += sizeof(long), laddr += m, len -= m;
841 }
842 while (len) {
843 if (len < sizeof(long))
844 u.val = ptrace(peek, pid, (char *) addr, 0);
845 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
846 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
847 perror("uload: POKE");
848 return -1;
849 }
850 addr += sizeof(long), laddr += m, len -= m;
851 }
852#endif
853 return 0;
854}
855
856int
857tload(pid, addr, len, laddr)
858int pid;
859int addr, len;
860char *laddr;
861{
862 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
863}
864
865int
866dload(pid, addr, len, laddr)
867int pid;
868int addr;
869int len;
870char *laddr;
871{
872 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
873}
874
875#endif /* SUNOS4 */
876
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000877#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000878
879int
880upeek(pid, off, res)
881int pid;
882long off;
883long *res;
884{
885 long val;
886
887#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
888 {
889 static int is_sun4m = -1;
890 struct utsname name;
891
892 /* Round up the usual suspects. */
893 if (is_sun4m == -1) {
894 if (uname(&name) < 0) {
895 perror("upeek: uname?");
896 exit(1);
897 }
898 is_sun4m = strcmp(name.machine, "sun4m") == 0;
899 if (is_sun4m) {
900 extern struct xlat struct_user_offsets[];
901 struct xlat *x;
902
903 for (x = struct_user_offsets; x->str; x++)
904 x->val += 1024;
905 }
906 }
907 if (is_sun4m)
908 off += 1024;
909 }
910#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
911 errno = 0;
912 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
913 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000914 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000915 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000916 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000917 return -1;
918 }
919 *res = val;
920 return 0;
921}
922
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000923#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000924
925long
926getpc(tcp)
927struct tcb *tcp;
928{
929
930#ifdef LINUX
931 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000932#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000933 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
934 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000935#elif defined(X86_64)
936 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
937 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000938#elif defined(IA64)
939 if (upeek(tcp->pid, PT_B0, &pc) < 0)
940 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000941#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000942 if (upeek(tcp->pid, 4*15, &pc) < 0)
943 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000944#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000945 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000946 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000947#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000948 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
949 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000950#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 if (upeek(tcp->pid, REG_PC, &pc) < 0)
952 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000953#elif defined(MIPS)
954 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
955 return -1;
956#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000957 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
959 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000960 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000961#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000962 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +0000963 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000964#elif defined(HPPA)
965 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
966 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000967#elif defined(SH)
968 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
969 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +0000970#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 return pc;
972#endif /* LINUX */
973
974#ifdef SUNOS4
975 /*
976 * Return current program counter for `pid'
977 * Assumes PC is never 0xffffffff
978 */
979 struct regs regs;
980
981 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
982 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
983 return -1;
984 }
985 return regs.r_pc;
986#endif /* SUNOS4 */
987
988#ifdef SVR4
989 /* XXX */
990 return 0;
991#endif /* SVR4 */
992
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000993#ifdef FREEBSD
994 struct reg regs;
995 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
996 return regs.r_eip;
997#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998}
999
1000void
1001printcall(tcp)
1002struct tcb *tcp;
1003{
1004
1005#ifdef LINUX
1006#ifdef I386
1007 long eip;
1008
1009 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1010 tprintf("[????????] ");
1011 return;
1012 }
1013 tprintf("[%08lx] ", eip);
Michal Ludvig0e035502002-09-23 15:41:01 +00001014#elif defined(X86_64)
1015 long rip;
1016
1017 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1018 tprintf("[????????] ");
1019 return;
1020 }
1021 tprintf("[%16lx] ", rip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001022#elif defined(IA62)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001023 long ip;
1024
1025 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1026 tprintf("[????????] ");
1027 return;
1028 }
1029 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001030#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 long pc;
1032
Roland McGratheb285352003-01-14 09:59:00 +00001033 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001034 tprintf ("[????????] ");
1035 return;
1036 }
1037 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001038#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001039 long pc;
1040
1041 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1042 tprintf ("[????????] ");
1043 return;
1044 }
1045 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001046#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001047 long pc;
1048
1049 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1050 tprintf ("[????????] ");
1051 return;
1052 }
1053 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001054#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001055 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1057 tprintf("[????????] ");
1058 return;
1059 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001060 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001061#elif defined(HPPA)
1062 long pc;
1063
1064 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1065 tprintf ("[????????] ");
1066 return;
1067 }
1068 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001069#elif defined(MIPS)
1070 long pc;
1071
1072 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1073 tprintf ("[????????] ");
1074 return;
1075 }
1076 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001077#elif defined(SH)
1078 long pc;
1079
1080 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1081 tprintf ("[????????] ");
1082 return;
1083 }
1084 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001085#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001086#endif /* LINUX */
1087
1088#ifdef SUNOS4
1089 struct regs regs;
1090
1091 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1092 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1093 tprintf("[????????] ");
1094 return;
1095 }
1096 tprintf("[%08x] ", regs.r_o7);
1097#endif /* SUNOS4 */
1098
1099#ifdef SVR4
1100 /* XXX */
1101 tprintf("[????????] ");
1102#endif
1103
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001104#ifdef FREEBSD
1105 struct reg regs;
1106 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1107 tprintf("[%08x] ", regs.r_eip);
1108#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109}
1110
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001111#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112
Roland McGrathd81f1d92003-01-09 06:53:34 +00001113#if defined LINUX
1114
1115#include <sys/syscall.h>
1116#ifndef CLONE_PTRACE
1117# define CLONE_PTRACE 0x00002000
1118#endif
1119
1120#ifdef IA64
1121
1122typedef unsigned long *arg_setup_state;
1123
1124static int
1125arg_setup(struct tcb *tcp, arg_setup_state *state)
1126{
1127 unsigned long *bsp, cfm, sof, sol;
1128
1129 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1130 return -1;
1131 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1132 return -1;
1133
1134 sof = (cfm >> 0) & 0x7f;
1135 sol = (cfm >> 7) & 0x7f;
1136 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1137
1138 *state = bsp;
1139 return 0;
1140}
1141
1142# define arg_finish_change(tcp, state) 0
1143
1144#ifdef SYS_fork
1145static int
1146get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1147{
1148 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
1149 sizeof(long), (void *) valp);
1150}
1151
1152static int
1153get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1154{
1155 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
1156 sizeof(long), (void *) valp);
1157}
1158#endif
1159
1160static int
1161set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1162{
1163 unsigned long *ap;
1164 ap = ia64_rse_skip_regs(*state, 0);
1165 errno = 0;
1166 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1167 return errno ? -1 : 0;
1168}
1169
1170static int
1171set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1172{
1173 unsigned long *ap;
1174 ap = ia64_rse_skip_regs(*state, 1);
1175 errno = 0;
1176 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1177 return errno ? -1 : 0;
1178}
1179
1180#elif defined (SPARC)
1181
1182typedef struct regs arg_setup_state;
1183
1184# define arg_setup(tcp, state) \
1185 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1186# define arg_finish_change(tcp, state) \
1187 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1188
1189# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1190# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1191# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1192# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001193# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001194
1195#else
1196
1197# if defined S390 || defined S390X
1198# define arg0_offset PT_ORIGGPR2
1199# define arg1_offset PT_GPR2
Roland McGrathe1df47f2003-01-14 09:46:15 +00001200# define restore_arg0(tcp, state, val) 0
1201# define restore_arg1(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001202# elif defined (ALPHA) || defined (MIPS)
1203# define arg0_offset REG_A0
1204# define arg1_offset (REG_A0+1)
1205# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001206# define arg0_offset (sizeof(unsigned long)*PT_R3)
1207# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001208# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001209# elif defined (HPPA)
1210# define arg0_offset PT_GR26
1211# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001212# elif defined (X86_64)
1213# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1214# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001215# else
1216# define arg0_offset 0
1217# define arg1_offset 4
Roland McGrathe1df47f2003-01-14 09:46:15 +00001218# if defined SH || defined ARM
1219# define restore_arg0(tcp, state, val) 0
1220# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001221# endif
1222
1223typedef int arg_setup_state;
1224
1225# define arg_setup(tcp, state) (0)
1226# define arg_finish_change(tcp, state) 0
1227# define get_arg0(tcp, cookie, valp) \
1228 (upeek ((tcp)->pid, arg0_offset, (valp)))
1229# define get_arg1(tcp, cookie, valp) \
1230 (upeek ((tcp)->pid, arg1_offset, (valp)))
1231
1232static int
1233set_arg0 (struct tcb *tcp, void *cookie, long val)
1234{
1235 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1236}
1237
1238static int
1239set_arg1 (struct tcb *tcp, void *cookie, long val)
1240{
1241 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1242}
1243
1244#endif
1245
Roland McGrathe1df47f2003-01-14 09:46:15 +00001246#ifndef restore_arg0
1247# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1248#endif
1249#ifndef restore_arg1
1250# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1251#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001252
1253int
1254setbpt(tcp)
1255struct tcb *tcp;
1256{
1257 extern int change_syscall(struct tcb *, int);
1258 arg_setup_state state;
1259
1260 if (tcp->flags & TCB_BPTSET) {
1261 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1262 return -1;
1263 }
1264
1265 switch (tcp->scno) {
1266#ifdef SYS_fork
1267 case SYS_fork:
1268 if (arg_setup (tcp, &state) < 0
1269 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1270 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1271 || change_syscall(tcp, SYS_clone) < 0
1272 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1273 || set_arg1 (tcp, &state, 0) < 0
1274 || arg_finish_change (tcp, &state) < 0)
1275 return -1;
1276 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1277 tcp->u_arg[1] = 0;
1278 tcp->flags |= TCB_BPTSET;
1279 return 0;
1280#endif
1281
1282 case SYS_clone:
1283#ifdef SYS_clone2
1284 case SYS_clone2:
1285#endif
1286 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1287 && (arg_setup (tcp, &state) < 0
1288 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1289 || arg_finish_change (tcp, &state) < 0))
1290 return -1;
1291 tcp->flags |= TCB_BPTSET;
1292 tcp->inst[0] = tcp->u_arg[0];
1293 tcp->inst[1] = tcp->u_arg[1];
1294 return 0;
1295
1296 default:
1297 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1298 tcp->scno, tcp->pid);
1299 break;
1300 }
1301
1302 return -1;
1303}
1304
1305int
1306clearbpt(tcp)
1307struct tcb *tcp;
1308{
1309 arg_setup_state state;
1310 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001311 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1312 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001313 || arg_finish_change (tcp, &state))
1314 return -1;
1315 tcp->flags &= ~TCB_BPTSET;
1316 return 0;
1317}
1318
1319#else
1320
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001321int
1322setbpt(tcp)
1323struct tcb *tcp;
1324{
1325
1326#ifdef LINUX
1327#ifdef SPARC
1328 /* We simply use the SunOS breakpoint code. */
1329
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001330 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331#define LOOPA 0x30800000 /* ba,a 0 */
1332
1333 if (tcp->flags & TCB_BPTSET) {
1334 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1335 return -1;
1336 }
1337 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1338 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1339 return -1;
1340 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001341 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342 errno = 0;
1343 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1344 if(errno) {
1345 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1346 return -1;
1347 }
1348
1349 /*
1350 * XXX - BRUTAL MODE ON
1351 * We cannot set a real BPT in the child, since it will not be
1352 * traced at the moment it will reach the trap and would probably
1353 * die with a core dump.
1354 * Thus, we are force our way in by taking out two instructions
1355 * and insert an eternal loop instead, in expectance of the SIGSTOP
1356 * generated by out PTRACE_ATTACH.
1357 * Of cause, if we evaporate ourselves in the middle of all this...
1358 */
1359 errno = 0;
1360 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1361 if(errno) {
1362 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1363 return -1;
1364 }
1365 tcp->flags |= TCB_BPTSET;
1366
1367#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001368#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001369 if (ia32) {
1370# define LOOP 0x0000feeb
1371 if (tcp->flags & TCB_BPTSET) {
1372 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1373 tcp->pid);
1374 return -1;
1375 }
1376 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1377 return -1;
1378 if (debug)
1379 fprintf(stderr, "[%d] setting bpt at %lx\n",
1380 tcp->pid, tcp->baddr);
1381 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1382 (char *) tcp->baddr, 0);
1383 if (errno) {
1384 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1385 return -1;
1386 }
1387 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1388 if (errno) {
1389 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1390 return -1;
1391 }
1392 tcp->flags |= TCB_BPTSET;
1393 } else {
1394 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001395 * Our strategy here is to replace the bundle that
1396 * contained the clone() syscall with a bundle of the
1397 * form:
1398 *
1399 * { 1: br 1b; br 1b; br 1b }
1400 *
1401 * This ensures that the newly forked child will loop
1402 * endlessly until we've got a chance to attach to it.
1403 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001404# define LOOP0 0x0000100000000017
1405# define LOOP1 0x4000000000200000
1406 unsigned long addr, ipsr;
1407 pid_t pid;
1408
1409 pid = tcp->pid;
1410 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1411 return -1;
1412 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1413 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001414 /* store "ri" in low two bits */
1415 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001416
1417 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001418 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1419 0);
1420 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1421 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001422 if (errno) {
1423 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1424 return -1;
1425 }
1426
1427 errno = 0;
1428 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1429 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1430 if (errno) {
1431 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1432 return -1;
1433 }
1434 tcp->flags |= TCB_BPTSET;
1435 }
1436#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001437
Michal Ludvig0e035502002-09-23 15:41:01 +00001438#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439#define LOOP 0x0000feeb
1440#elif defined (M68K)
1441#define LOOP 0x60fe0000
1442#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001443#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001445#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001447#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001448#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001449#define LOOP 0x1000ffff
1450#elif defined(S390)
1451#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001452#elif defined(S390X)
1453#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001454#elif defined(HPPA)
1455#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001456#elif defined(SH)
1457#ifdef __LITTLE_ENDIAN__
1458#define LOOP 0x0000affe
1459#else
1460#define LOOP 0xfeaf0000
1461#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462#else
1463#error unknown architecture
1464#endif
1465
1466 if (tcp->flags & TCB_BPTSET) {
1467 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1468 return -1;
1469 }
1470#if defined (I386)
1471 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1472 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001473#elif defined (X86_64)
1474 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1475 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476#elif defined (M68K)
1477 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1478 return -1;
1479#elif defined (ALPHA)
1480 return -1;
1481#elif defined (ARM)
1482 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001483#elif defined (MIPS)
1484 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001486 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001488#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001489 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1490 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001491#elif defined(HPPA)
1492 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1493 return -1;
1494 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001495#elif defined(SH)
1496 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1497 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498#else
1499#error unknown architecture
1500#endif
1501 if (debug)
1502 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1503 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1504 if (errno) {
1505 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1506 return -1;
1507 }
1508 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1509 if (errno) {
1510 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1511 return -1;
1512 }
1513 tcp->flags |= TCB_BPTSET;
1514
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001515#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001516#endif /* SPARC */
1517#endif /* LINUX */
1518
1519#ifdef SUNOS4
1520#ifdef SPARC /* This code is slightly sparc specific */
1521
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001522 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001523#define BPT 0x91d02001 /* ta 1 */
1524#define LOOP 0x10800000 /* ba 0 */
1525#define LOOPA 0x30800000 /* ba,a 0 */
1526#define NOP 0x01000000
1527#if LOOPA
1528 static int loopdeloop[1] = {LOOPA};
1529#else
1530 static int loopdeloop[2] = {LOOP, NOP};
1531#endif
1532
1533 if (tcp->flags & TCB_BPTSET) {
1534 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1535 return -1;
1536 }
1537 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1538 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1539 return -1;
1540 }
1541 tcp->baddr = regs.r_o7 + 8;
1542 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1543 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1544 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1545 return -1;
1546 }
1547
1548 /*
1549 * XXX - BRUTAL MODE ON
1550 * We cannot set a real BPT in the child, since it will not be
1551 * traced at the moment it will reach the trap and would probably
1552 * die with a core dump.
1553 * Thus, we are force our way in by taking out two instructions
1554 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1555 * generated by out PTRACE_ATTACH.
1556 * Of cause, if we evaporate ourselves in the middle of all this...
1557 */
1558 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1559 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1560 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1561 return -1;
1562 }
1563 tcp->flags |= TCB_BPTSET;
1564
1565#endif /* SPARC */
1566#endif /* SUNOS4 */
1567
1568 return 0;
1569}
1570
1571int
1572clearbpt(tcp)
1573struct tcb *tcp;
1574{
1575
1576#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001577#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001578 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001579#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001581#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001583#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001584 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001585#elif defined(HPPA)
1586 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001587#elif defined(SH)
1588 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001589#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001590
1591#ifdef SPARC
1592 /* Again, we borrow the SunOS breakpoint code. */
1593 if (!(tcp->flags & TCB_BPTSET)) {
1594 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1595 return -1;
1596 }
1597 errno = 0;
1598 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1599 if(errno) {
1600 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1601 return -1;
1602 }
1603 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001604#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001605 if (ia32) {
1606 unsigned long addr;
1607
1608 if (debug)
1609 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1610 if (!(tcp->flags & TCB_BPTSET)) {
1611 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1612 return -1;
1613 }
1614 errno = 0;
1615 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1616 if (errno) {
1617 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1618 return -1;
1619 }
1620 tcp->flags &= ~TCB_BPTSET;
1621
1622 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1623 return -1;
1624 if (addr != tcp->baddr) {
1625 /* The breakpoint has not been reached yet. */
1626 if (debug)
1627 fprintf(stderr,
1628 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1629 addr, tcp->baddr);
1630 return 0;
1631 }
1632 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001633 unsigned long addr, ipsr;
1634 pid_t pid;
1635
1636 pid = tcp->pid;
1637
1638 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1639 return -1;
1640 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1641 return -1;
1642
1643 /* restore original bundle: */
1644 errno = 0;
1645 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1646 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1647 if (errno) {
1648 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1649 return -1;
1650 }
1651
1652 /* restore original "ri" in ipsr: */
1653 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1654 errno = 0;
1655 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1656 if (errno) {
1657 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1658 return -1;
1659 }
1660
1661 tcp->flags &= ~TCB_BPTSET;
1662
1663 if (addr != (tcp->baddr & ~0x3)) {
1664 /* the breakpoint has not been reached yet. */
1665 if (debug)
1666 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1667 addr, tcp->baddr);
1668 return 0;
1669 }
1670 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001671#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672
1673 if (debug)
1674 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1675 if (!(tcp->flags & TCB_BPTSET)) {
1676 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1677 return -1;
1678 }
1679 errno = 0;
1680 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1681 if (errno) {
1682 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1683 return -1;
1684 }
1685 tcp->flags &= ~TCB_BPTSET;
1686
1687#ifdef I386
1688 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1689 return -1;
1690 if (eip != tcp->baddr) {
1691 /* The breakpoint has not been reached yet. */
1692 if (debug)
1693 fprintf(stderr,
1694 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1695 eip, tcp->baddr);
1696 return 0;
1697 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001698#elif defined(X86_64)
1699 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1700 return -1;
1701 if (eip != tcp->baddr) {
1702 /* The breakpoint has not been reached yet. */
1703 if (debug)
1704 fprintf(stderr,
1705 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1706 eip, tcp->baddr);
1707 return 0;
1708 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001709#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001710 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711 return -1;
1712 if (pc != tcp->baddr) {
1713 /* The breakpoint has not been reached yet. */
1714 if (debug)
1715 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1716 pc, tcp->baddr);
1717 return 0;
1718 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001719#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001720 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1721 return -1;
1722 if (pc != tcp->baddr) {
1723 /* The breakpoint has not been reached yet. */
1724 if (debug)
1725 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1726 pc, tcp->baddr);
1727 return 0;
1728 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001729#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1731 return -1;
1732 if (pc != tcp->baddr) {
1733 /* The breakpoint has not been reached yet. */
1734 if (debug)
1735 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1736 pc, tcp->baddr);
1737 return 0;
1738 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001739#elif defined(HPPA)
1740 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1741 return -1;
1742 iaoq &= ~0x03;
1743 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1744 /* The breakpoint has not been reached yet. */
1745 if (debug)
1746 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1747 iaoq, tcp->baddr);
1748 return 0;
1749 }
1750 iaoq = tcp->baddr | 3;
1751 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1752 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1753 * has no significant effect.
1754 */
1755 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1756 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001757#elif defined(SH)
1758 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1759 return -1;
1760 if (pc != tcp->baddr) {
1761 /* The breakpoint has not been reached yet. */
1762 if (debug)
1763 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1764 pc, tcp->baddr);
1765 return 0;
1766 }
1767
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001768#endif /* arch */
1769#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001770#endif /* LINUX */
1771
1772#ifdef SUNOS4
1773#ifdef SPARC
1774
1775#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001776 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001777#endif
1778
1779 if (!(tcp->flags & TCB_BPTSET)) {
1780 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1781 return -1;
1782 }
1783 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1784 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1785 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1786 return -1;
1787 }
1788 tcp->flags &= ~TCB_BPTSET;
1789
1790#if !LOOPA
1791 /*
1792 * Since we don't have a single instruction breakpoint, we may have
1793 * to adjust the program counter after removing the our `breakpoint'.
1794 */
1795 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1796 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1797 return -1;
1798 }
1799 if ((regs.r_pc < tcp->baddr) ||
1800 (regs.r_pc > tcp->baddr + 4)) {
1801 /* The breakpoint has not been reached yet */
1802 if (debug)
1803 fprintf(stderr,
1804 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1805 regs.r_pc, tcp->parent->baddr);
1806 return 0;
1807 }
1808 if (regs.r_pc != tcp->baddr)
1809 if (debug)
1810 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1811 regs.r_pc, tcp->baddr);
1812
1813 regs.r_pc = tcp->baddr;
1814 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1815 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1816 return -1;
1817 }
1818#endif /* LOOPA */
1819#endif /* SPARC */
1820#endif /* SUNOS4 */
1821
1822 return 0;
1823}
1824
Roland McGrathd81f1d92003-01-09 06:53:34 +00001825#endif
1826
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001827#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828
1829#ifdef SUNOS4
1830
1831static int
1832getex(pid, hdr)
1833int pid;
1834struct exec *hdr;
1835{
1836 int n;
1837
1838 for (n = 0; n < sizeof *hdr; n += 4) {
1839 long res;
1840 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1841 return -1;
1842 memcpy(((char *) hdr) + n, &res, 4);
1843 }
1844 if (debug) {
1845 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1846 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1847 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1848 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1849 }
1850 return 0;
1851}
1852
1853int
1854fixvfork(tcp)
1855struct tcb *tcp;
1856{
1857 int pid = tcp->pid;
1858 /*
1859 * Change `vfork' in a freshly exec'ed dynamically linked
1860 * executable's (internal) symbol table to plain old `fork'
1861 */
1862
1863 struct exec hdr;
1864 struct link_dynamic dyn;
1865 struct link_dynamic_2 ld;
1866 char *strtab, *cp;
1867
1868 if (getex(pid, &hdr) < 0)
1869 return -1;
1870 if (!hdr.a_dynamic)
1871 return -1;
1872
1873 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1874 fprintf(stderr, "Cannot read DYNAMIC\n");
1875 return -1;
1876 }
1877 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1878 fprintf(stderr, "Cannot read link_dynamic_2\n");
1879 return -1;
1880 }
1881 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1882 fprintf(stderr, "fixvfork: out of memory\n");
1883 return -1;
1884 }
1885 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1886 (int)ld.ld_symb_size, strtab) < 0)
1887 goto err;
1888
1889#if 0
1890 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1891 fprintf(stderr, "[symbol: %s]\n", cp);
1892 cp += strlen(cp)+1;
1893 }
1894 return 0;
1895#endif
1896 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1897 if (strcmp(cp, "_vfork") == 0) {
1898 if (debug)
1899 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1900 strcpy(cp, "_fork");
1901 break;
1902 }
1903 cp += strlen(cp)+1;
1904 }
1905 if (cp < strtab + ld.ld_symb_size)
1906 /*
1907 * Write entire symbol table back to avoid
1908 * memory alignment bugs in ptrace
1909 */
1910 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1911 (int)ld.ld_symb_size, strtab) < 0)
1912 goto err;
1913
1914 free(strtab);
1915 return 0;
1916
1917err:
1918 free(strtab);
1919 return -1;
1920}
1921
1922#endif /* SUNOS4 */