blob: efed279770338e75e7ff4280eeafd277631c2106 [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) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001266#ifdef SYS_vfork
1267 case SYS_vfork:
1268#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001269#ifdef SYS_fork
1270 case SYS_fork:
1271 if (arg_setup (tcp, &state) < 0
1272 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1273 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1274 || change_syscall(tcp, SYS_clone) < 0
1275 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1276 || set_arg1 (tcp, &state, 0) < 0
1277 || arg_finish_change (tcp, &state) < 0)
1278 return -1;
1279 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1280 tcp->u_arg[1] = 0;
1281 tcp->flags |= TCB_BPTSET;
1282 return 0;
1283#endif
1284
1285 case SYS_clone:
1286#ifdef SYS_clone2
1287 case SYS_clone2:
1288#endif
1289 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1290 && (arg_setup (tcp, &state) < 0
1291 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1292 || arg_finish_change (tcp, &state) < 0))
1293 return -1;
1294 tcp->flags |= TCB_BPTSET;
1295 tcp->inst[0] = tcp->u_arg[0];
1296 tcp->inst[1] = tcp->u_arg[1];
1297 return 0;
1298
1299 default:
1300 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1301 tcp->scno, tcp->pid);
1302 break;
1303 }
1304
1305 return -1;
1306}
1307
1308int
1309clearbpt(tcp)
1310struct tcb *tcp;
1311{
1312 arg_setup_state state;
1313 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001314 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1315 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001316 || arg_finish_change (tcp, &state))
1317 return -1;
1318 tcp->flags &= ~TCB_BPTSET;
1319 return 0;
1320}
1321
1322#else
1323
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001324int
1325setbpt(tcp)
1326struct tcb *tcp;
1327{
1328
1329#ifdef LINUX
1330#ifdef SPARC
1331 /* We simply use the SunOS breakpoint code. */
1332
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001333 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334#define LOOPA 0x30800000 /* ba,a 0 */
1335
1336 if (tcp->flags & TCB_BPTSET) {
1337 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1338 return -1;
1339 }
1340 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1341 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1342 return -1;
1343 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001344 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345 errno = 0;
1346 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1347 if(errno) {
1348 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1349 return -1;
1350 }
1351
1352 /*
1353 * XXX - BRUTAL MODE ON
1354 * We cannot set a real BPT in the child, since it will not be
1355 * traced at the moment it will reach the trap and would probably
1356 * die with a core dump.
1357 * Thus, we are force our way in by taking out two instructions
1358 * and insert an eternal loop instead, in expectance of the SIGSTOP
1359 * generated by out PTRACE_ATTACH.
1360 * Of cause, if we evaporate ourselves in the middle of all this...
1361 */
1362 errno = 0;
1363 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1364 if(errno) {
1365 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1366 return -1;
1367 }
1368 tcp->flags |= TCB_BPTSET;
1369
1370#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001371#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001372 if (ia32) {
1373# define LOOP 0x0000feeb
1374 if (tcp->flags & TCB_BPTSET) {
1375 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1376 tcp->pid);
1377 return -1;
1378 }
1379 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1380 return -1;
1381 if (debug)
1382 fprintf(stderr, "[%d] setting bpt at %lx\n",
1383 tcp->pid, tcp->baddr);
1384 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1385 (char *) tcp->baddr, 0);
1386 if (errno) {
1387 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1388 return -1;
1389 }
1390 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1391 if (errno) {
1392 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1393 return -1;
1394 }
1395 tcp->flags |= TCB_BPTSET;
1396 } else {
1397 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001398 * Our strategy here is to replace the bundle that
1399 * contained the clone() syscall with a bundle of the
1400 * form:
1401 *
1402 * { 1: br 1b; br 1b; br 1b }
1403 *
1404 * This ensures that the newly forked child will loop
1405 * endlessly until we've got a chance to attach to it.
1406 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001407# define LOOP0 0x0000100000000017
1408# define LOOP1 0x4000000000200000
1409 unsigned long addr, ipsr;
1410 pid_t pid;
1411
1412 pid = tcp->pid;
1413 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1414 return -1;
1415 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1416 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001417 /* store "ri" in low two bits */
1418 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001419
1420 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001421 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1422 0);
1423 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1424 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001425 if (errno) {
1426 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1427 return -1;
1428 }
1429
1430 errno = 0;
1431 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1432 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1433 if (errno) {
1434 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1435 return -1;
1436 }
1437 tcp->flags |= TCB_BPTSET;
1438 }
1439#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001440
Michal Ludvig0e035502002-09-23 15:41:01 +00001441#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442#define LOOP 0x0000feeb
1443#elif defined (M68K)
1444#define LOOP 0x60fe0000
1445#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001446#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001448#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001450#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001451#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001452#define LOOP 0x1000ffff
1453#elif defined(S390)
1454#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001455#elif defined(S390X)
1456#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001457#elif defined(HPPA)
1458#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001459#elif defined(SH)
1460#ifdef __LITTLE_ENDIAN__
1461#define LOOP 0x0000affe
1462#else
1463#define LOOP 0xfeaf0000
1464#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001465#else
1466#error unknown architecture
1467#endif
1468
1469 if (tcp->flags & TCB_BPTSET) {
1470 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1471 return -1;
1472 }
1473#if defined (I386)
1474 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1475 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001476#elif defined (X86_64)
1477 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1478 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479#elif defined (M68K)
1480 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1481 return -1;
1482#elif defined (ALPHA)
1483 return -1;
1484#elif defined (ARM)
1485 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001486#elif defined (MIPS)
1487 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001488#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001489 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001490 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001491#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001492 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1493 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001494#elif defined(HPPA)
1495 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1496 return -1;
1497 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001498#elif defined(SH)
1499 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1500 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501#else
1502#error unknown architecture
1503#endif
1504 if (debug)
1505 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1506 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1507 if (errno) {
1508 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1509 return -1;
1510 }
1511 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1512 if (errno) {
1513 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1514 return -1;
1515 }
1516 tcp->flags |= TCB_BPTSET;
1517
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001518#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001519#endif /* SPARC */
1520#endif /* LINUX */
1521
1522#ifdef SUNOS4
1523#ifdef SPARC /* This code is slightly sparc specific */
1524
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001525 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001526#define BPT 0x91d02001 /* ta 1 */
1527#define LOOP 0x10800000 /* ba 0 */
1528#define LOOPA 0x30800000 /* ba,a 0 */
1529#define NOP 0x01000000
1530#if LOOPA
1531 static int loopdeloop[1] = {LOOPA};
1532#else
1533 static int loopdeloop[2] = {LOOP, NOP};
1534#endif
1535
1536 if (tcp->flags & TCB_BPTSET) {
1537 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1538 return -1;
1539 }
1540 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1541 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1542 return -1;
1543 }
1544 tcp->baddr = regs.r_o7 + 8;
1545 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1546 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1547 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1548 return -1;
1549 }
1550
1551 /*
1552 * XXX - BRUTAL MODE ON
1553 * We cannot set a real BPT in the child, since it will not be
1554 * traced at the moment it will reach the trap and would probably
1555 * die with a core dump.
1556 * Thus, we are force our way in by taking out two instructions
1557 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1558 * generated by out PTRACE_ATTACH.
1559 * Of cause, if we evaporate ourselves in the middle of all this...
1560 */
1561 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1562 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1563 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1564 return -1;
1565 }
1566 tcp->flags |= TCB_BPTSET;
1567
1568#endif /* SPARC */
1569#endif /* SUNOS4 */
1570
1571 return 0;
1572}
1573
1574int
1575clearbpt(tcp)
1576struct tcb *tcp;
1577{
1578
1579#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001580#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001582#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001584#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001585 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001586#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001587 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001588#elif defined(HPPA)
1589 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001590#elif defined(SH)
1591 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001592#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001593
1594#ifdef SPARC
1595 /* Again, we borrow the SunOS breakpoint code. */
1596 if (!(tcp->flags & TCB_BPTSET)) {
1597 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1598 return -1;
1599 }
1600 errno = 0;
1601 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1602 if(errno) {
1603 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1604 return -1;
1605 }
1606 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001607#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001608 if (ia32) {
1609 unsigned long addr;
1610
1611 if (debug)
1612 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1613 if (!(tcp->flags & TCB_BPTSET)) {
1614 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1615 return -1;
1616 }
1617 errno = 0;
1618 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1619 if (errno) {
1620 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1621 return -1;
1622 }
1623 tcp->flags &= ~TCB_BPTSET;
1624
1625 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1626 return -1;
1627 if (addr != tcp->baddr) {
1628 /* The breakpoint has not been reached yet. */
1629 if (debug)
1630 fprintf(stderr,
1631 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1632 addr, tcp->baddr);
1633 return 0;
1634 }
1635 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001636 unsigned long addr, ipsr;
1637 pid_t pid;
1638
1639 pid = tcp->pid;
1640
1641 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1642 return -1;
1643 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1644 return -1;
1645
1646 /* restore original bundle: */
1647 errno = 0;
1648 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1649 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1650 if (errno) {
1651 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1652 return -1;
1653 }
1654
1655 /* restore original "ri" in ipsr: */
1656 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1657 errno = 0;
1658 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1659 if (errno) {
1660 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1661 return -1;
1662 }
1663
1664 tcp->flags &= ~TCB_BPTSET;
1665
1666 if (addr != (tcp->baddr & ~0x3)) {
1667 /* the breakpoint has not been reached yet. */
1668 if (debug)
1669 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1670 addr, tcp->baddr);
1671 return 0;
1672 }
1673 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001674#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675
1676 if (debug)
1677 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1678 if (!(tcp->flags & TCB_BPTSET)) {
1679 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1680 return -1;
1681 }
1682 errno = 0;
1683 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1684 if (errno) {
1685 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1686 return -1;
1687 }
1688 tcp->flags &= ~TCB_BPTSET;
1689
1690#ifdef I386
1691 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1692 return -1;
1693 if (eip != tcp->baddr) {
1694 /* The breakpoint has not been reached yet. */
1695 if (debug)
1696 fprintf(stderr,
1697 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1698 eip, tcp->baddr);
1699 return 0;
1700 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001701#elif defined(X86_64)
1702 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1703 return -1;
1704 if (eip != tcp->baddr) {
1705 /* The breakpoint has not been reached yet. */
1706 if (debug)
1707 fprintf(stderr,
1708 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1709 eip, tcp->baddr);
1710 return 0;
1711 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001712#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001713 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714 return -1;
1715 if (pc != tcp->baddr) {
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 pc, tcp->baddr);
1720 return 0;
1721 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001722#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001723 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1724 return -1;
1725 if (pc != tcp->baddr) {
1726 /* The breakpoint has not been reached yet. */
1727 if (debug)
1728 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1729 pc, tcp->baddr);
1730 return 0;
1731 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001732#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001733 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1734 return -1;
1735 if (pc != tcp->baddr) {
1736 /* The breakpoint has not been reached yet. */
1737 if (debug)
1738 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1739 pc, tcp->baddr);
1740 return 0;
1741 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001742#elif defined(HPPA)
1743 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1744 return -1;
1745 iaoq &= ~0x03;
1746 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1747 /* The breakpoint has not been reached yet. */
1748 if (debug)
1749 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1750 iaoq, tcp->baddr);
1751 return 0;
1752 }
1753 iaoq = tcp->baddr | 3;
1754 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1755 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1756 * has no significant effect.
1757 */
1758 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1759 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001760#elif defined(SH)
1761 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1762 return -1;
1763 if (pc != tcp->baddr) {
1764 /* The breakpoint has not been reached yet. */
1765 if (debug)
1766 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1767 pc, tcp->baddr);
1768 return 0;
1769 }
1770
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001771#endif /* arch */
1772#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001773#endif /* LINUX */
1774
1775#ifdef SUNOS4
1776#ifdef SPARC
1777
1778#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001779 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001780#endif
1781
1782 if (!(tcp->flags & TCB_BPTSET)) {
1783 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1784 return -1;
1785 }
1786 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1787 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1788 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1789 return -1;
1790 }
1791 tcp->flags &= ~TCB_BPTSET;
1792
1793#if !LOOPA
1794 /*
1795 * Since we don't have a single instruction breakpoint, we may have
1796 * to adjust the program counter after removing the our `breakpoint'.
1797 */
1798 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1799 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1800 return -1;
1801 }
1802 if ((regs.r_pc < tcp->baddr) ||
1803 (regs.r_pc > tcp->baddr + 4)) {
1804 /* The breakpoint has not been reached yet */
1805 if (debug)
1806 fprintf(stderr,
1807 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1808 regs.r_pc, tcp->parent->baddr);
1809 return 0;
1810 }
1811 if (regs.r_pc != tcp->baddr)
1812 if (debug)
1813 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1814 regs.r_pc, tcp->baddr);
1815
1816 regs.r_pc = tcp->baddr;
1817 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1818 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1819 return -1;
1820 }
1821#endif /* LOOPA */
1822#endif /* SPARC */
1823#endif /* SUNOS4 */
1824
1825 return 0;
1826}
1827
Roland McGrathd81f1d92003-01-09 06:53:34 +00001828#endif
1829
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001830#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001831
1832#ifdef SUNOS4
1833
1834static int
1835getex(pid, hdr)
1836int pid;
1837struct exec *hdr;
1838{
1839 int n;
1840
1841 for (n = 0; n < sizeof *hdr; n += 4) {
1842 long res;
1843 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1844 return -1;
1845 memcpy(((char *) hdr) + n, &res, 4);
1846 }
1847 if (debug) {
1848 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1849 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1850 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1851 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1852 }
1853 return 0;
1854}
1855
1856int
1857fixvfork(tcp)
1858struct tcb *tcp;
1859{
1860 int pid = tcp->pid;
1861 /*
1862 * Change `vfork' in a freshly exec'ed dynamically linked
1863 * executable's (internal) symbol table to plain old `fork'
1864 */
1865
1866 struct exec hdr;
1867 struct link_dynamic dyn;
1868 struct link_dynamic_2 ld;
1869 char *strtab, *cp;
1870
1871 if (getex(pid, &hdr) < 0)
1872 return -1;
1873 if (!hdr.a_dynamic)
1874 return -1;
1875
1876 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1877 fprintf(stderr, "Cannot read DYNAMIC\n");
1878 return -1;
1879 }
1880 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1881 fprintf(stderr, "Cannot read link_dynamic_2\n");
1882 return -1;
1883 }
1884 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1885 fprintf(stderr, "fixvfork: out of memory\n");
1886 return -1;
1887 }
1888 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1889 (int)ld.ld_symb_size, strtab) < 0)
1890 goto err;
1891
1892#if 0
1893 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1894 fprintf(stderr, "[symbol: %s]\n", cp);
1895 cp += strlen(cp)+1;
1896 }
1897 return 0;
1898#endif
1899 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1900 if (strcmp(cp, "_vfork") == 0) {
1901 if (debug)
1902 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1903 strcpy(cp, "_fork");
1904 break;
1905 }
1906 cp += strlen(cp)+1;
1907 }
1908 if (cp < strtab + ld.ld_symb_size)
1909 /*
1910 * Write entire symbol table back to avoid
1911 * memory alignment bugs in ptrace
1912 */
1913 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1914 (int)ld.ld_symb_size, strtab) < 0)
1915 goto err;
1916
1917 free(strtab);
1918 return 0;
1919
1920err:
1921 free(strtab);
1922 return -1;
1923}
1924
1925#endif /* SUNOS4 */