blob: 8343e2425df70ebf0f8eec0bed7449fc14fbfc9d [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
Roland McGrathd81f1d92003-01-09 06:53:34 +000038#include <signal.h>
39#include <sys/syscall.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040#include <sys/user.h>
41#include <sys/param.h>
42#include <fcntl.h>
John Hughes1d08dcf2001-07-10 13:48:44 +000043#if HAVE_SYS_UIO_H
44#include <sys/uio.h>
45#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000046#ifdef SUNOS4
47#include <machine/reg.h>
48#include <a.out.h>
49#include <link.h>
50#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000051
Wichert Akkerman43a74822000-06-27 17:33:32 +000052#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
Wichert Akkerman36915a11999-07-13 15:45:02 +000053#include <linux/ptrace.h>
Roland McGrath1e85cf92002-12-16 20:40:54 +000054#endif
Wichert Akkerman36915a11999-07-13 15:45:02 +000055
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000056#if defined(LINUX) && defined(IA64)
Roland McGrathd81f1d92003-01-09 06:53:34 +000057# include <asm/ptrace_offsets.h>
58# include <asm/rse.h>
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000059#endif
60
Wichert Akkerman36915a11999-07-13 15:45:02 +000061#ifdef HAVE_SYS_REG_H
62#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000063# define PTRACE_PEEKUSR PTRACE_PEEKUSER
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
66#include <linux/ptrace.h>
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000067#endif
68
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000069#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
70#include <sys/utsname.h>
71#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
72
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000073#if defined(LINUX) && defined(SPARC)
74
Roland McGrath4db26242003-01-30 20:15:19 +000075# define fpq kernel_fpq
76# define fq kernel_fq
77# define fpu kernel_fpu
78# include <asm/reg.h>
79# undef fpq
80# undef fq
81# undef fpu
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000082
83#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084
85#include <linux/unistd.h>
86
87#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
88 type5,arg5,syscall) \
89type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
90{ \
91 long __res; \
92\
93__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
94 "or %%g0, %2, %%o1\n\t" \
95 "or %%g0, %3, %%o2\n\t" \
96 "or %%g0, %4, %%o3\n\t" \
97 "or %%g0, %5, %%o4\n\t" \
98 "or %%g0, %6, %%g1\n\t" \
99 "t 0x10\n\t" \
100 "bcc 1f\n\t" \
101 "or %%g0, %%o0, %0\n\t" \
102 "sub %%g0, %%o0, %0\n\t" \
103 "1:\n\t" \
104 : "=r" (__res) \
105 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
106 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
107 "i" (__NR_##syscall) \
108 : "g1", "o0", "o1", "o2", "o3", "o4"); \
109if (__res>=0) \
110 return (type) __res; \
111errno = -__res; \
112return -1; \
113}
114
115static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
116
117#define _ptrace
118
119#endif
120
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000121#endif
122
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123/* macros */
124#ifndef MAX
125#define MAX(a,b) (((a) > (b)) ? (a) : (b))
126#endif
127#ifndef MIN
128#define MIN(a,b) (((a) < (b)) ? (a) : (b))
129#endif
130
131void
132tv_tv(tv, a, b)
133struct timeval *tv;
134int a;
135int b;
136{
137 tv->tv_sec = a;
138 tv->tv_usec = b;
139}
140
141int
142tv_nz(a)
143struct timeval *a;
144{
145 return a->tv_sec || a->tv_usec;
146}
147
148int
149tv_cmp(a, b)
150struct timeval *a, *b;
151{
152 if (a->tv_sec < b->tv_sec
153 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
154 return -1;
155 if (a->tv_sec > b->tv_sec
156 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
157 return 1;
158 return 0;
159}
160
161double
162tv_float(tv)
163struct timeval *tv;
164{
165 return tv->tv_sec + tv->tv_usec/1000000.0;
166}
167
168void
169tv_add(tv, a, b)
170struct timeval *tv, *a, *b;
171{
172 tv->tv_sec = a->tv_sec + b->tv_sec;
173 tv->tv_usec = a->tv_usec + b->tv_usec;
174 if (tv->tv_usec > 1000000) {
175 tv->tv_sec++;
176 tv->tv_usec -= 1000000;
177 }
178}
179
180void
181tv_sub(tv, a, b)
182struct timeval *tv, *a, *b;
183{
184 tv->tv_sec = a->tv_sec - b->tv_sec;
185 tv->tv_usec = a->tv_usec - b->tv_usec;
186 if (((long) tv->tv_usec) < 0) {
187 tv->tv_sec--;
188 tv->tv_usec += 1000000;
189 }
190}
191
192void
193tv_div(tv, a, n)
194struct timeval *tv, *a;
195int n;
196{
197 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
198 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
199 tv->tv_usec %= 1000000;
200}
201
202void
203tv_mul(tv, a, n)
204struct timeval *tv, *a;
205int n;
206{
207 tv->tv_usec = a->tv_usec * n;
208 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
209 tv->tv_usec %= 1000000;
210}
211
212char *
213xlookup(xlat, val)
214struct xlat *xlat;
215int val;
216{
217 for (; xlat->str != NULL; xlat++)
218 if (xlat->val == val)
219 return xlat->str;
220 return NULL;
221}
222
223/*
224 * Print entry in struct xlat table, if there.
225 */
226void
227printxval(xlat, val, dflt)
228struct xlat *xlat;
229int val;
230char *dflt;
231{
232 char *str = xlookup(xlat, val);
233
234 if (str)
235 tprintf("%s", str);
236 else
237 tprintf("%#x /* %s */", val, dflt);
238}
239
240/*
241 * Interpret `xlat' as an array of flags
242 * print the entries whose bits are on in `flags'
243 * return # of flags printed.
244 */
245int
246addflags(xlat, flags)
247struct xlat *xlat;
248int flags;
249{
250 int n;
251
252 for (n = 0; xlat->str; xlat++) {
253 if (xlat->val && (flags & xlat->val) == xlat->val) {
254 tprintf("|%s", xlat->str);
255 flags &= ~xlat->val;
256 n++;
257 }
258 }
259 if (flags) {
260 tprintf("|%#x", flags);
261 n++;
262 }
263 return n;
264}
265
266int
267printflags(xlat, flags)
268struct xlat *xlat;
269int flags;
270{
271 int n;
272 char *sep;
273
274 if (flags == 0 && xlat->val == 0) {
275 tprintf("%s", xlat->str);
276 return 1;
277 }
278
279 sep = "";
280 for (n = 0; xlat->str; xlat++) {
281 if (xlat->val && (flags & xlat->val) == xlat->val) {
282 tprintf("%s%s", sep, xlat->str);
283 flags &= ~xlat->val;
284 sep = "|";
285 n++;
286 }
287 }
288 if (flags) {
289 tprintf("%s%#x", sep, flags);
290 n++;
291 }
292 return n;
293}
294
295void
296printnum(tcp, addr, fmt)
297struct tcb *tcp;
298long addr;
299char *fmt;
300{
Roland McGratheb285352003-01-14 09:59:00 +0000301 long num;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302
303 if (!addr) {
304 tprintf("NULL");
305 return;
306 }
307 if (umove(tcp, addr, &num) < 0) {
308 tprintf("%#lx", addr);
309 return;
310 }
311 tprintf("[");
312 tprintf(fmt, num);
313 tprintf("]");
314}
315
316static char path[MAXPATHLEN + 1];
317
318void
319string_quote(str)
320char *str;
321{
322 char buf[2 * MAXPATHLEN + 1];
323 char *s;
324
325 if (!strpbrk(str, "\"\'\\")) {
326 tprintf("\"%s\"", str);
327 return;
328 }
329 for (s = buf; *str; str++) {
330 switch (*str) {
331 case '\"': case '\'': case '\\':
332 *s++ = '\\'; *s++ = *str; break;
333 default:
334 *s++ = *str; break;
335 }
336 }
337 *s = '\0';
338 tprintf("\"%s\"", buf);
339}
340
341void
342printpath(tcp, addr)
343struct tcb *tcp;
344long addr;
345{
346 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
347 tprintf("%#lx", addr);
348 else
349 string_quote(path);
350 return;
351}
352
353void
354printpathn(tcp, addr, n)
355struct tcb *tcp;
356long addr;
357int n;
358{
359 if (umovestr(tcp, addr, n, path) < 0)
360 tprintf("%#lx", addr);
361 else {
362 path[n] = '\0';
363 string_quote(path);
364 }
365}
366
367void
368printstr(tcp, addr, len)
369struct tcb *tcp;
370long addr;
371int len;
372{
373 static unsigned char *str = NULL;
374 static char *outstr;
375 int i, n, c, usehex;
376 char *s, *outend;
377
378 if (!addr) {
379 tprintf("NULL");
380 return;
381 }
382 if (!str) {
383 if ((str = malloc(max_strlen)) == NULL
384 || (outstr = malloc(2*max_strlen)) == NULL) {
385 fprintf(stderr, "printstr: no memory\n");
386 tprintf("%#lx", addr);
387 return;
388 }
389 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000390 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391 if (len < 0) {
392 n = max_strlen;
393 if (umovestr(tcp, addr, n, (char *) str) < 0) {
394 tprintf("%#lx", addr);
395 return;
396 }
397 }
398 else {
399 n = MIN(len, max_strlen);
400 if (umoven(tcp, addr, n, (char *) str) < 0) {
401 tprintf("%#lx", addr);
402 return;
403 }
404 }
405
406 usehex = 0;
407 if (xflag > 1)
408 usehex = 1;
409 else if (xflag) {
410 for (i = 0; i < n; i++) {
411 c = str[i];
412 if (len < 0 && c == '\0')
413 break;
414 if (!isprint(c) && !isspace(c)) {
415 usehex = 1;
416 break;
417 }
418 }
419 }
420
421 s = outstr;
422 *s++ = '\"';
423
424 if (usehex) {
425 for (i = 0; i < n; i++) {
426 c = str[i];
427 if (len < 0 && c == '\0')
428 break;
429 sprintf(s, "\\x%02x", c);
430 s += 4;
431 if (s > outend)
432 break;
433 }
434 }
435 else {
436 for (i = 0; i < n; i++) {
437 c = str[i];
438 if (len < 0 && c == '\0')
439 break;
440 switch (c) {
441 case '\"': case '\'': case '\\':
442 *s++ = '\\'; *s++ = c; break;
443 case '\f':
444 *s++ = '\\'; *s++ = 'f'; break;
445 case '\n':
446 *s++ = '\\'; *s++ = 'n'; break;
447 case '\r':
448 *s++ = '\\'; *s++ = 'r'; break;
449 case '\t':
450 *s++ = '\\'; *s++ = 't'; break;
451 case '\v':
452 *s++ = '\\'; *s++ = 'v'; break;
453 default:
454 if (isprint(c))
455 *s++ = c;
456 else if (i < n - 1 && isdigit(str[i + 1])) {
457 sprintf(s, "\\%03o", c);
458 s += 4;
459 }
460 else {
461 sprintf(s, "\\%o", c);
462 s += strlen(s);
463 }
464 break;
465 }
466 if (s > outend)
467 break;
468 }
469 }
470
471 *s++ = '\"';
472 if (i < len || (len < 0 && (i == n || s > outend))) {
473 *s++ = '.'; *s++ = '.'; *s++ = '.';
474 }
475 *s = '\0';
476 tprintf("%s", outstr);
477}
478
John Hughes1d08dcf2001-07-10 13:48:44 +0000479#if HAVE_SYS_UIO_H
480void
481dumpiov(tcp, len, addr)
482struct tcb * tcp;
483int len;
484long addr;
485{
486 struct iovec *iov;
487 int i;
488
Roland McGrath1e85cf92002-12-16 20:40:54 +0000489
John Hughes1d08dcf2001-07-10 13:48:44 +0000490 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
491 fprintf(stderr, "dump: No memory");
492 return;
493 }
494 if (umoven(tcp, addr,
495 len * sizeof *iov, (char *) iov) >= 0) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000496
John Hughes1d08dcf2001-07-10 13:48:44 +0000497 for (i = 0; i < len; i++) {
498 /* include the buffer number to make it easy to
499 * match up the trace with the source */
500 tprintf(" * %lu bytes in buffer %d\n",
501 (unsigned long)iov[i].iov_len, i);
502 dumpstr(tcp, (long) iov[i].iov_base,
503 iov[i].iov_len);
504 }
505 }
506 free((char *) iov);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000507
John Hughes1d08dcf2001-07-10 13:48:44 +0000508}
509#endif
510
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511void
512dumpstr(tcp, addr, len)
513struct tcb *tcp;
514long addr;
515int len;
516{
517 static int strsize = -1;
518 static unsigned char *str;
519 static char outstr[80];
520 char *s;
521 int i, j;
522
523 if (strsize < len) {
524 if (str)
525 free(str);
526 if ((str = malloc(len)) == NULL) {
527 fprintf(stderr, "dump: no memory\n");
528 return;
529 }
530 strsize = len;
531 }
532
533 if (umoven(tcp, addr, len, (char *) str) < 0)
534 return;
535
536 for (i = 0; i < len; i += 16) {
537 s = outstr;
538 sprintf(s, " | %05x ", i);
539 s += 9;
540 for (j = 0; j < 16; j++) {
541 if (j == 8)
542 *s++ = ' ';
543 if (i + j < len) {
544 sprintf(s, " %02x", str[i + j]);
545 s += 3;
546 }
547 else {
548 *s++ = ' '; *s++ = ' '; *s++ = ' ';
549 }
550 }
551 *s++ = ' '; *s++ = ' ';
552 for (j = 0; j < 16; j++) {
553 if (j == 8)
554 *s++ = ' ';
555 if (i + j < len) {
556 if (isprint(str[i + j]))
557 *s++ = str[i + j];
558 else
559 *s++ = '.';
560 }
561 else
562 *s++ = ' ';
563 }
564 tprintf("%s |\n", outstr);
565 }
566}
567
568#define PAGMASK (~(PAGSIZ - 1))
569/*
570 * move `len' bytes of data from process `pid'
571 * at address `addr' to our space at `laddr'
572 */
573int
574umoven(tcp, addr, len, laddr)
575struct tcb *tcp;
576long addr;
577int len;
578char *laddr;
579{
580
581#ifdef LINUX
582 int pid = tcp->pid;
583 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000584 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000585 union {
586 long val;
587 char x[sizeof(long)];
588 } u;
589
590 if (addr & (sizeof(long) - 1)) {
591 /* addr not a multiple of sizeof(long) */
592 n = addr - (addr & -sizeof(long)); /* residue */
593 addr &= -sizeof(long); /* residue */
594 errno = 0;
595 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
596 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000597 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598 /* Ran into 'end of memory' - stupid "printpath" */
599 return 0;
600 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000601 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602 perror("ptrace: umoven");
603 return -1;
604 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000605 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
607 addr += sizeof(long), laddr += m, len -= m;
608 }
609 while (len) {
610 errno = 0;
611 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
612 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000613 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614 /* Ran into 'end of memory' - stupid "printpath" */
615 return 0;
616 }
Roland McGrath4db26242003-01-30 20:15:19 +0000617 if (addr != 0)
618 perror("ptrace: umoven");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000619 return -1;
620 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000621 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000622 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
623 addr += sizeof(long), laddr += m, len -= m;
624 }
625#endif /* LINUX */
626
627#ifdef SUNOS4
628 int pid = tcp->pid;
629#if 0
630 int n, m;
631 union {
632 long val;
633 char x[sizeof(long)];
634 } u;
635
636 if (addr & (sizeof(long) - 1)) {
637 /* addr not a multiple of sizeof(long) */
638 n = addr - (addr & -sizeof(long)); /* residue */
639 addr &= -sizeof(long); /* residue */
640 errno = 0;
641 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
642 if (errno) {
643 perror("umoven");
644 return -1;
645 }
646 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
647 addr += sizeof(long), laddr += m, len -= m;
648 }
649 while (len) {
650 errno = 0;
651 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
652 if (errno) {
653 perror("umoven");
654 return -1;
655 }
656 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
657 addr += sizeof(long), laddr += m, len -= m;
658 }
659#else /* !oldway */
660 int n;
661
662 while (len) {
663 n = MIN(len, PAGSIZ);
664 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
665 if (ptrace(PTRACE_READDATA, pid,
666 (char *) addr, len, laddr) < 0) {
667 perror("umoven: ptrace(PTRACE_READDATA, ...)");
668 abort();
669 return -1;
670 }
671 len -= n;
672 addr += n;
673 laddr += n;
674 }
675#endif /* !oldway */
676#endif /* SUNOS4 */
677
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000678#ifdef USE_PROCFS
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000679#ifdef HAVE_MP_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000680 int fd = tcp->pfd_as;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000681#else
John Hughesaa09c6b2001-05-15 14:53:43 +0000682 int fd = tcp->pfd;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683#endif
John Hughesaa09c6b2001-05-15 14:53:43 +0000684 lseek(fd, addr, SEEK_SET);
685 if (read(fd, laddr, len) == -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000686 return -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000687#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000688
689 return 0;
690}
691
692/*
693 * like `umove' but make the additional effort of looking
694 * for a terminating zero byte.
695 */
696int
697umovestr(tcp, addr, len, laddr)
698struct tcb *tcp;
699long addr;
700int len;
701char *laddr;
702{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000703#ifdef USE_PROCFS
John Hughesaa09c6b2001-05-15 14:53:43 +0000704#ifdef HAVE_MP_PROCFS
705 int fd = tcp->pfd_as;
706#else
707 int fd = tcp->pfd;
708#endif
709 /* Some systems (e.g. FreeBSD) can be upset if we read off the
710 end of valid memory, avoid this by trying to read up
711 to page boundaries. But we don't know what a page is (and
712 getpagesize(2) (if it exists) doesn't necessarily return
713 hardware page size). Assume all pages >= 1024 (a-historical
714 I know) */
715
716 int page = 1024; /* How to find this? */
717 int move = page - (addr & (page - 1));
718 int left = len;
719
720 lseek(fd, addr, SEEK_SET);
721
722 while (left) {
723 if (move > left) move = left;
John Hughes9cecf7f2001-10-16 10:20:22 +0000724 if ((move = read(fd, laddr, move)) <= 0)
John Hughesaa09c6b2001-05-15 14:53:43 +0000725 return left != len ? 0 : -1;
726 if (memchr (laddr, 0, move)) break;
727 left -= move;
728 laddr += move;
729 addr += move;
730 move = page;
731 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000732#else /* !USE_PROCFS */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000733 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000734 int pid = tcp->pid;
735 int i, n, m;
736 union {
737 long val;
738 char x[sizeof(long)];
739 } u;
740
741 if (addr & (sizeof(long) - 1)) {
742 /* addr not a multiple of sizeof(long) */
743 n = addr - (addr & -sizeof(long)); /* residue */
744 addr &= -sizeof(long); /* residue */
745 errno = 0;
746 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
747 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000748 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000749 /* Ran into 'end of memory' - stupid "printpath" */
750 return 0;
751 }
752 perror("umovestr");
753 return -1;
754 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000755 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
757 while (n & (sizeof(long) - 1))
758 if (u.x[n++] == '\0')
759 return 0;
760 addr += sizeof(long), laddr += m, len -= m;
761 }
762 while (len) {
763 errno = 0;
764 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
765 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000766 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000767 /* Ran into 'end of memory' - stupid "printpath" */
768 return 0;
769 }
770 perror("umovestr");
771 return -1;
772 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000773 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000774 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
775 for (i = 0; i < sizeof(long); i++)
776 if (u.x[i] == '\0')
777 return 0;
778
779 addr += sizeof(long), laddr += m, len -= m;
780 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000781#endif /* !USE_PROCFS */
John Hughesaa09c6b2001-05-15 14:53:43 +0000782 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783}
784
785#ifdef LINUX
786#ifndef SPARC
787#define PTRACE_WRITETEXT 101
788#define PTRACE_WRITEDATA 102
789#endif /* !SPARC */
790#endif /* LINUX */
791
792#ifdef SUNOS4
793
794static int
795uload(cmd, pid, addr, len, laddr)
796int cmd;
797int pid;
798long addr;
799int len;
800char *laddr;
801{
802#if 0
803 int n;
804
805 while (len) {
806 n = MIN(len, PAGSIZ);
807 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
808 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
809 perror("uload: ptrace(PTRACE_WRITE, ...)");
810 return -1;
811 }
812 len -= n;
813 addr += n;
814 laddr += n;
815 }
816#else
817 int peek, poke;
818 int n, m;
819 union {
820 long val;
821 char x[sizeof(long)];
822 } u;
823
824 if (cmd == PTRACE_WRITETEXT) {
825 peek = PTRACE_PEEKTEXT;
826 poke = PTRACE_POKETEXT;
827 }
828 else {
829 peek = PTRACE_PEEKDATA;
830 poke = PTRACE_POKEDATA;
831 }
832 if (addr & (sizeof(long) - 1)) {
833 /* addr not a multiple of sizeof(long) */
834 n = addr - (addr & -sizeof(long)); /* residue */
835 addr &= -sizeof(long);
836 errno = 0;
837 u.val = ptrace(peek, pid, (char *) addr, 0);
838 if (errno) {
839 perror("uload: POKE");
840 return -1;
841 }
842 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
843 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
844 perror("uload: POKE");
845 return -1;
846 }
847 addr += sizeof(long), laddr += m, len -= m;
848 }
849 while (len) {
850 if (len < sizeof(long))
851 u.val = ptrace(peek, pid, (char *) addr, 0);
852 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
853 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
854 perror("uload: POKE");
855 return -1;
856 }
857 addr += sizeof(long), laddr += m, len -= m;
858 }
859#endif
860 return 0;
861}
862
863int
864tload(pid, addr, len, laddr)
865int pid;
866int addr, len;
867char *laddr;
868{
869 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
870}
871
872int
873dload(pid, addr, len, laddr)
874int pid;
875int addr;
876int len;
877char *laddr;
878{
879 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
880}
881
882#endif /* SUNOS4 */
883
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000884#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885
886int
887upeek(pid, off, res)
888int pid;
889long off;
890long *res;
891{
892 long val;
893
894#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
895 {
896 static int is_sun4m = -1;
897 struct utsname name;
898
899 /* Round up the usual suspects. */
900 if (is_sun4m == -1) {
901 if (uname(&name) < 0) {
902 perror("upeek: uname?");
903 exit(1);
904 }
905 is_sun4m = strcmp(name.machine, "sun4m") == 0;
906 if (is_sun4m) {
907 extern struct xlat struct_user_offsets[];
908 struct xlat *x;
909
910 for (x = struct_user_offsets; x->str; x++)
911 x->val += 1024;
912 }
913 }
914 if (is_sun4m)
915 off += 1024;
916 }
917#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
918 errno = 0;
919 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
920 if (val == -1 && errno) {
Roland McGrath1e85cf92002-12-16 20:40:54 +0000921 char buf[60];
Michal Ludvig0e035502002-09-23 15:41:01 +0000922 sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)",pid,off);
Roland McGrath1e85cf92002-12-16 20:40:54 +0000923 perror(buf);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000924 return -1;
925 }
926 *res = val;
927 return 0;
928}
929
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000930#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931
932long
933getpc(tcp)
934struct tcb *tcp;
935{
936
937#ifdef LINUX
938 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000939#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000940 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
941 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000942#elif defined(X86_64)
943 if (upeek(tcp->pid, 8*RIP, &pc) < 0)
944 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000945#elif defined(IA64)
946 if (upeek(tcp->pid, PT_B0, &pc) < 0)
947 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000948#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949 if (upeek(tcp->pid, 4*15, &pc) < 0)
950 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000951#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000952 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000953 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000954#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
956 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000957#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 if (upeek(tcp->pid, REG_PC, &pc) < 0)
959 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000960#elif defined(MIPS)
961 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
962 return -1;
963#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000964 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
966 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000967 pc = regs.r_pc;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000968#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000969 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Michal Ludvig10a88d02002-10-07 14:31:00 +0000970 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000971#elif defined(HPPA)
972 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0)
973 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000974#elif defined(SH)
975 if (upeek(tcp->pid, 4*REG_PC ,&pc) < 0)
976 return -1;
Wichert Akkerman7a0b6491999-12-23 15:08:17 +0000977#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978 return pc;
979#endif /* LINUX */
980
981#ifdef SUNOS4
982 /*
983 * Return current program counter for `pid'
984 * Assumes PC is never 0xffffffff
985 */
986 struct regs regs;
987
988 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
989 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
990 return -1;
991 }
992 return regs.r_pc;
993#endif /* SUNOS4 */
994
995#ifdef SVR4
996 /* XXX */
997 return 0;
998#endif /* SVR4 */
999
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001000#ifdef FREEBSD
1001 struct reg regs;
1002 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1003 return regs.r_eip;
1004#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005}
1006
1007void
1008printcall(tcp)
1009struct tcb *tcp;
1010{
1011
1012#ifdef LINUX
1013#ifdef I386
1014 long eip;
1015
1016 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
1017 tprintf("[????????] ");
1018 return;
1019 }
1020 tprintf("[%08lx] ", eip);
Michal Ludvig0e035502002-09-23 15:41:01 +00001021#elif defined(X86_64)
1022 long rip;
1023
1024 if (upeek(tcp->pid, 8*RIP, &rip) < 0) {
1025 tprintf("[????????] ");
1026 return;
1027 }
1028 tprintf("[%16lx] ", rip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001029#elif defined(IA62)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001030 long ip;
1031
1032 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
1033 tprintf("[????????] ");
1034 return;
1035 }
1036 tprintf("[%08lx] ", ip);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001037#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038 long pc;
1039
Roland McGratheb285352003-01-14 09:59:00 +00001040 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001041 tprintf ("[????????] ");
1042 return;
1043 }
1044 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001045#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001046 long pc;
1047
1048 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
1049 tprintf ("[????????] ");
1050 return;
1051 }
1052 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001053#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 long pc;
1055
1056 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
1057 tprintf ("[????????] ");
1058 return;
1059 }
1060 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001061#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001062 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001063 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1064 tprintf("[????????] ");
1065 return;
1066 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001067 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001068#elif defined(HPPA)
1069 long pc;
1070
1071 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) {
1072 tprintf ("[????????] ");
1073 return;
1074 }
1075 tprintf("[%08lx] ", pc);
Wichert Akkerman75c422b2001-04-10 10:22:50 +00001076#elif defined(MIPS)
1077 long pc;
1078
1079 if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
1080 tprintf ("[????????] ");
1081 return;
1082 }
1083 tprintf("[%08lx] ", pc);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001084#elif defined(SH)
1085 long pc;
1086
1087 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
1088 tprintf ("[????????] ");
1089 return;
1090 }
1091 tprintf("[%08lx] ", pc);
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001092#endif /* !architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093#endif /* LINUX */
1094
1095#ifdef SUNOS4
1096 struct regs regs;
1097
1098 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1099 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1100 tprintf("[????????] ");
1101 return;
1102 }
1103 tprintf("[%08x] ", regs.r_o7);
1104#endif /* SUNOS4 */
1105
1106#ifdef SVR4
1107 /* XXX */
1108 tprintf("[????????] ");
1109#endif
1110
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001111#ifdef FREEBSD
1112 struct reg regs;
1113 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1114 tprintf("[%08x] ", regs.r_eip);
1115#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001116}
1117
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001118#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001119
Roland McGrathd81f1d92003-01-09 06:53:34 +00001120#if defined LINUX
1121
1122#include <sys/syscall.h>
1123#ifndef CLONE_PTRACE
1124# define CLONE_PTRACE 0x00002000
1125#endif
1126
1127#ifdef IA64
1128
1129typedef unsigned long *arg_setup_state;
1130
1131static int
1132arg_setup(struct tcb *tcp, arg_setup_state *state)
1133{
1134 unsigned long *bsp, cfm, sof, sol;
1135
1136 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) < 0)
1137 return -1;
1138 if (upeek(tcp->pid, PT_CFM, (long *) &cfm) < 0)
1139 return -1;
1140
1141 sof = (cfm >> 0) & 0x7f;
1142 sol = (cfm >> 7) & 0x7f;
1143 bsp = ia64_rse_skip_regs(bsp, -sof + sol);
1144
1145 *state = bsp;
1146 return 0;
1147}
1148
1149# define arg_finish_change(tcp, state) 0
1150
1151#ifdef SYS_fork
1152static int
1153get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1154{
1155 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 0),
1156 sizeof(long), (void *) valp);
1157}
1158
1159static int
1160get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1161{
1162 return umoven (tcp, (unsigned long) ia64_rse_skip_regs(*state, 1),
1163 sizeof(long), (void *) valp);
1164}
1165#endif
1166
1167static int
1168set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1169{
1170 unsigned long *ap;
1171 ap = ia64_rse_skip_regs(*state, 0);
1172 errno = 0;
1173 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1174 return errno ? -1 : 0;
1175}
1176
1177static int
1178set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1179{
1180 unsigned long *ap;
1181 ap = ia64_rse_skip_regs(*state, 1);
1182 errno = 0;
1183 ptrace(PTRACE_POKEDATA, tcp->pid, (void *) ap, val);
1184 return errno ? -1 : 0;
1185}
1186
1187#elif defined (SPARC)
1188
1189typedef struct regs arg_setup_state;
1190
1191# define arg_setup(tcp, state) \
1192 (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1193# define arg_finish_change(tcp, state) \
1194 (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1195
1196# define get_arg0(tcp, state, valp) (*(valp) = (state)->r_o0, 0)
1197# define get_arg1(tcp, state, valp) (*(valp) = (state)->r_o1, 0)
1198# define set_arg0(tcp, state, val) ((state)->r_o0 = (val), 0)
1199# define set_arg1(tcp, state, val) ((state)->r_o1 = (val), 0)
Roland McGrathe1df47f2003-01-14 09:46:15 +00001200# define restore_arg0(tcp, state, val) 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001201
1202#else
1203
1204# if defined S390 || defined S390X
Roland McGrath7b308222003-01-20 09:04:36 +00001205/* Note: this is only true for the `clone' system call, which handles
1206 arguments specially. We could as well say that its first two arguments
1207 are swapped relative to other architectures, but that would just be
1208 another #ifdef in the calls. */
1209# define arg0_offset PT_GPR3
1210# define arg1_offset PT_ORIGGPR2
1211# define restore_arg0(tcp, state, val) ((void) (state), 0)
1212# define restore_arg1(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001213# elif defined (ALPHA) || defined (MIPS)
1214# define arg0_offset REG_A0
1215# define arg1_offset (REG_A0+1)
1216# elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001217# define arg0_offset (sizeof(unsigned long)*PT_R3)
1218# define arg1_offset (sizeof(unsigned long)*PT_R4)
Roland McGrath7b308222003-01-20 09:04:36 +00001219# define restore_arg0(tcp, state, val) ((void) (state), 0)
Roland McGrathd81f1d92003-01-09 06:53:34 +00001220# elif defined (HPPA)
1221# define arg0_offset PT_GR26
1222# define arg1_offset (PT_GR26-4)
Roland McGrath7f33cc32003-01-10 20:51:00 +00001223# elif defined (X86_64)
1224# define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1225# define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001226# else
1227# define arg0_offset 0
1228# define arg1_offset 4
Roland McGrathe1df47f2003-01-14 09:46:15 +00001229# if defined SH || defined ARM
1230# define restore_arg0(tcp, state, val) 0
1231# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001232# endif
1233
1234typedef int arg_setup_state;
1235
1236# define arg_setup(tcp, state) (0)
1237# define arg_finish_change(tcp, state) 0
1238# define get_arg0(tcp, cookie, valp) \
1239 (upeek ((tcp)->pid, arg0_offset, (valp)))
1240# define get_arg1(tcp, cookie, valp) \
1241 (upeek ((tcp)->pid, arg1_offset, (valp)))
1242
1243static int
1244set_arg0 (struct tcb *tcp, void *cookie, long val)
1245{
1246 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1247}
1248
1249static int
1250set_arg1 (struct tcb *tcp, void *cookie, long val)
1251{
1252 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1253}
1254
1255#endif
1256
Roland McGrathe1df47f2003-01-14 09:46:15 +00001257#ifndef restore_arg0
1258# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1259#endif
1260#ifndef restore_arg1
1261# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1262#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001263
1264int
1265setbpt(tcp)
1266struct tcb *tcp;
1267{
1268 extern int change_syscall(struct tcb *, int);
1269 arg_setup_state state;
1270
1271 if (tcp->flags & TCB_BPTSET) {
1272 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1273 return -1;
1274 }
1275
1276 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001277#ifdef SYS_vfork
1278 case SYS_vfork:
1279#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001280#ifdef SYS_fork
1281 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001282#endif
1283#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001284 if (arg_setup (tcp, &state) < 0
1285 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1286 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1287 || change_syscall(tcp, SYS_clone) < 0
1288 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1289 || set_arg1 (tcp, &state, 0) < 0
1290 || arg_finish_change (tcp, &state) < 0)
1291 return -1;
1292 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1293 tcp->u_arg[1] = 0;
1294 tcp->flags |= TCB_BPTSET;
1295 return 0;
1296#endif
1297
1298 case SYS_clone:
1299#ifdef SYS_clone2
1300 case SYS_clone2:
1301#endif
1302 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1303 && (arg_setup (tcp, &state) < 0
1304 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1305 || arg_finish_change (tcp, &state) < 0))
1306 return -1;
1307 tcp->flags |= TCB_BPTSET;
1308 tcp->inst[0] = tcp->u_arg[0];
1309 tcp->inst[1] = tcp->u_arg[1];
1310 return 0;
1311
1312 default:
1313 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1314 tcp->scno, tcp->pid);
1315 break;
1316 }
1317
1318 return -1;
1319}
1320
1321int
1322clearbpt(tcp)
1323struct tcb *tcp;
1324{
1325 arg_setup_state state;
1326 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001327 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1328 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001329 || arg_finish_change (tcp, &state))
1330 return -1;
1331 tcp->flags &= ~TCB_BPTSET;
1332 return 0;
1333}
1334
1335#else
1336
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337int
1338setbpt(tcp)
1339struct tcb *tcp;
1340{
1341
1342#ifdef LINUX
1343#ifdef SPARC
1344 /* We simply use the SunOS breakpoint code. */
1345
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001346 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001347#define LOOPA 0x30800000 /* ba,a 0 */
1348
1349 if (tcp->flags & TCB_BPTSET) {
1350 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1351 return -1;
1352 }
1353 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1354 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1355 return -1;
1356 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001357 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358 errno = 0;
1359 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1360 if(errno) {
1361 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1362 return -1;
1363 }
1364
1365 /*
1366 * XXX - BRUTAL MODE ON
1367 * We cannot set a real BPT in the child, since it will not be
1368 * traced at the moment it will reach the trap and would probably
1369 * die with a core dump.
1370 * Thus, we are force our way in by taking out two instructions
1371 * and insert an eternal loop instead, in expectance of the SIGSTOP
1372 * generated by out PTRACE_ATTACH.
1373 * Of cause, if we evaporate ourselves in the middle of all this...
1374 */
1375 errno = 0;
1376 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1377 if(errno) {
1378 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1379 return -1;
1380 }
1381 tcp->flags |= TCB_BPTSET;
1382
1383#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001384#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001385 if (ia32) {
1386# define LOOP 0x0000feeb
1387 if (tcp->flags & TCB_BPTSET) {
1388 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1389 tcp->pid);
1390 return -1;
1391 }
1392 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1393 return -1;
1394 if (debug)
1395 fprintf(stderr, "[%d] setting bpt at %lx\n",
1396 tcp->pid, tcp->baddr);
1397 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1398 (char *) tcp->baddr, 0);
1399 if (errno) {
1400 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1401 return -1;
1402 }
1403 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1404 if (errno) {
1405 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1406 return -1;
1407 }
1408 tcp->flags |= TCB_BPTSET;
1409 } else {
1410 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001411 * Our strategy here is to replace the bundle that
1412 * contained the clone() syscall with a bundle of the
1413 * form:
1414 *
1415 * { 1: br 1b; br 1b; br 1b }
1416 *
1417 * This ensures that the newly forked child will loop
1418 * endlessly until we've got a chance to attach to it.
1419 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001420# define LOOP0 0x0000100000000017
1421# define LOOP1 0x4000000000200000
1422 unsigned long addr, ipsr;
1423 pid_t pid;
1424
1425 pid = tcp->pid;
1426 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1427 return -1;
1428 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1429 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001430 /* store "ri" in low two bits */
1431 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001432
1433 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001434 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1435 0);
1436 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1437 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001438 if (errno) {
1439 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1440 return -1;
1441 }
1442
1443 errno = 0;
1444 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1445 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1446 if (errno) {
1447 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1448 return -1;
1449 }
1450 tcp->flags |= TCB_BPTSET;
1451 }
1452#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001453
Michal Ludvig0e035502002-09-23 15:41:01 +00001454#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001455#define LOOP 0x0000feeb
1456#elif defined (M68K)
1457#define LOOP 0x60fe0000
1458#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001459#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001461#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001463#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001464#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001465#define LOOP 0x1000ffff
1466#elif defined(S390)
1467#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001468#elif defined(S390X)
1469#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001470#elif defined(HPPA)
1471#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001472#elif defined(SH)
1473#ifdef __LITTLE_ENDIAN__
1474#define LOOP 0x0000affe
1475#else
1476#define LOOP 0xfeaf0000
1477#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001478#else
1479#error unknown architecture
1480#endif
1481
1482 if (tcp->flags & TCB_BPTSET) {
1483 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1484 return -1;
1485 }
1486#if defined (I386)
1487 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1488 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001489#elif defined (X86_64)
1490 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1491 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492#elif defined (M68K)
1493 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1494 return -1;
1495#elif defined (ALPHA)
1496 return -1;
1497#elif defined (ARM)
1498 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001499#elif defined (MIPS)
1500 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001502 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001504#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001505 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1506 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001507#elif defined(HPPA)
1508 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1509 return -1;
1510 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001511#elif defined(SH)
1512 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1513 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001514#else
1515#error unknown architecture
1516#endif
1517 if (debug)
1518 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1519 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1520 if (errno) {
1521 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1522 return -1;
1523 }
1524 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1525 if (errno) {
1526 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1527 return -1;
1528 }
1529 tcp->flags |= TCB_BPTSET;
1530
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001531#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001532#endif /* SPARC */
1533#endif /* LINUX */
1534
1535#ifdef SUNOS4
1536#ifdef SPARC /* This code is slightly sparc specific */
1537
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001538 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539#define BPT 0x91d02001 /* ta 1 */
1540#define LOOP 0x10800000 /* ba 0 */
1541#define LOOPA 0x30800000 /* ba,a 0 */
1542#define NOP 0x01000000
1543#if LOOPA
1544 static int loopdeloop[1] = {LOOPA};
1545#else
1546 static int loopdeloop[2] = {LOOP, NOP};
1547#endif
1548
1549 if (tcp->flags & TCB_BPTSET) {
1550 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1551 return -1;
1552 }
1553 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1554 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1555 return -1;
1556 }
1557 tcp->baddr = regs.r_o7 + 8;
1558 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1559 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1560 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1561 return -1;
1562 }
1563
1564 /*
1565 * XXX - BRUTAL MODE ON
1566 * We cannot set a real BPT in the child, since it will not be
1567 * traced at the moment it will reach the trap and would probably
1568 * die with a core dump.
1569 * Thus, we are force our way in by taking out two instructions
1570 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1571 * generated by out PTRACE_ATTACH.
1572 * Of cause, if we evaporate ourselves in the middle of all this...
1573 */
1574 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1575 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1576 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1577 return -1;
1578 }
1579 tcp->flags |= TCB_BPTSET;
1580
1581#endif /* SPARC */
1582#endif /* SUNOS4 */
1583
1584 return 0;
1585}
1586
1587int
1588clearbpt(tcp)
1589struct tcb *tcp;
1590{
1591
1592#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001593#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001595#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001596 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001597#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001599#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001600 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001601#elif defined(HPPA)
1602 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001603#elif defined(SH)
1604 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001605#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001606
1607#ifdef SPARC
1608 /* Again, we borrow the SunOS breakpoint code. */
1609 if (!(tcp->flags & TCB_BPTSET)) {
1610 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1611 return -1;
1612 }
1613 errno = 0;
1614 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1615 if(errno) {
1616 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1617 return -1;
1618 }
1619 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001620#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001621 if (ia32) {
1622 unsigned long addr;
1623
1624 if (debug)
1625 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1626 if (!(tcp->flags & TCB_BPTSET)) {
1627 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1628 return -1;
1629 }
1630 errno = 0;
1631 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1632 if (errno) {
1633 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1634 return -1;
1635 }
1636 tcp->flags &= ~TCB_BPTSET;
1637
1638 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1639 return -1;
1640 if (addr != tcp->baddr) {
1641 /* The breakpoint has not been reached yet. */
1642 if (debug)
1643 fprintf(stderr,
1644 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1645 addr, tcp->baddr);
1646 return 0;
1647 }
1648 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001649 unsigned long addr, ipsr;
1650 pid_t pid;
1651
1652 pid = tcp->pid;
1653
1654 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1655 return -1;
1656 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1657 return -1;
1658
1659 /* restore original bundle: */
1660 errno = 0;
1661 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1662 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1663 if (errno) {
1664 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1665 return -1;
1666 }
1667
1668 /* restore original "ri" in ipsr: */
1669 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1670 errno = 0;
1671 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1672 if (errno) {
1673 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1674 return -1;
1675 }
1676
1677 tcp->flags &= ~TCB_BPTSET;
1678
1679 if (addr != (tcp->baddr & ~0x3)) {
1680 /* the breakpoint has not been reached yet. */
1681 if (debug)
1682 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1683 addr, tcp->baddr);
1684 return 0;
1685 }
1686 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001687#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688
1689 if (debug)
1690 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1691 if (!(tcp->flags & TCB_BPTSET)) {
1692 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1693 return -1;
1694 }
1695 errno = 0;
1696 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1697 if (errno) {
1698 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1699 return -1;
1700 }
1701 tcp->flags &= ~TCB_BPTSET;
1702
1703#ifdef I386
1704 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1705 return -1;
1706 if (eip != tcp->baddr) {
1707 /* The breakpoint has not been reached yet. */
1708 if (debug)
1709 fprintf(stderr,
1710 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1711 eip, tcp->baddr);
1712 return 0;
1713 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001714#elif defined(X86_64)
1715 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1716 return -1;
1717 if (eip != tcp->baddr) {
1718 /* The breakpoint has not been reached yet. */
1719 if (debug)
1720 fprintf(stderr,
1721 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1722 eip, tcp->baddr);
1723 return 0;
1724 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001725#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001726 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727 return -1;
1728 if (pc != tcp->baddr) {
1729 /* The breakpoint has not been reached yet. */
1730 if (debug)
1731 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1732 pc, tcp->baddr);
1733 return 0;
1734 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001735#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1737 return -1;
1738 if (pc != tcp->baddr) {
1739 /* The breakpoint has not been reached yet. */
1740 if (debug)
1741 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1742 pc, tcp->baddr);
1743 return 0;
1744 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001745#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1747 return -1;
1748 if (pc != tcp->baddr) {
1749 /* The breakpoint has not been reached yet. */
1750 if (debug)
1751 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1752 pc, tcp->baddr);
1753 return 0;
1754 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001755#elif defined(HPPA)
1756 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1757 return -1;
1758 iaoq &= ~0x03;
1759 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1760 /* The breakpoint has not been reached yet. */
1761 if (debug)
1762 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1763 iaoq, tcp->baddr);
1764 return 0;
1765 }
1766 iaoq = tcp->baddr | 3;
1767 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1768 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1769 * has no significant effect.
1770 */
1771 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1772 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001773#elif defined(SH)
1774 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1775 return -1;
1776 if (pc != tcp->baddr) {
1777 /* The breakpoint has not been reached yet. */
1778 if (debug)
1779 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1780 pc, tcp->baddr);
1781 return 0;
1782 }
1783
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001784#endif /* arch */
1785#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001786#endif /* LINUX */
1787
1788#ifdef SUNOS4
1789#ifdef SPARC
1790
1791#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001792 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001793#endif
1794
1795 if (!(tcp->flags & TCB_BPTSET)) {
1796 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1797 return -1;
1798 }
1799 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1800 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1801 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1802 return -1;
1803 }
1804 tcp->flags &= ~TCB_BPTSET;
1805
1806#if !LOOPA
1807 /*
1808 * Since we don't have a single instruction breakpoint, we may have
1809 * to adjust the program counter after removing the our `breakpoint'.
1810 */
1811 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1812 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1813 return -1;
1814 }
1815 if ((regs.r_pc < tcp->baddr) ||
1816 (regs.r_pc > tcp->baddr + 4)) {
1817 /* The breakpoint has not been reached yet */
1818 if (debug)
1819 fprintf(stderr,
1820 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1821 regs.r_pc, tcp->parent->baddr);
1822 return 0;
1823 }
1824 if (regs.r_pc != tcp->baddr)
1825 if (debug)
1826 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1827 regs.r_pc, tcp->baddr);
1828
1829 regs.r_pc = tcp->baddr;
1830 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1831 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1832 return -1;
1833 }
1834#endif /* LOOPA */
1835#endif /* SPARC */
1836#endif /* SUNOS4 */
1837
1838 return 0;
1839}
1840
Roland McGrathd81f1d92003-01-09 06:53:34 +00001841#endif
1842
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001843#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001844
1845#ifdef SUNOS4
1846
1847static int
1848getex(pid, hdr)
1849int pid;
1850struct exec *hdr;
1851{
1852 int n;
1853
1854 for (n = 0; n < sizeof *hdr; n += 4) {
1855 long res;
1856 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1857 return -1;
1858 memcpy(((char *) hdr) + n, &res, 4);
1859 }
1860 if (debug) {
1861 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1862 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1863 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1864 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1865 }
1866 return 0;
1867}
1868
1869int
1870fixvfork(tcp)
1871struct tcb *tcp;
1872{
1873 int pid = tcp->pid;
1874 /*
1875 * Change `vfork' in a freshly exec'ed dynamically linked
1876 * executable's (internal) symbol table to plain old `fork'
1877 */
1878
1879 struct exec hdr;
1880 struct link_dynamic dyn;
1881 struct link_dynamic_2 ld;
1882 char *strtab, *cp;
1883
1884 if (getex(pid, &hdr) < 0)
1885 return -1;
1886 if (!hdr.a_dynamic)
1887 return -1;
1888
1889 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1890 fprintf(stderr, "Cannot read DYNAMIC\n");
1891 return -1;
1892 }
1893 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1894 fprintf(stderr, "Cannot read link_dynamic_2\n");
1895 return -1;
1896 }
1897 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1898 fprintf(stderr, "fixvfork: out of memory\n");
1899 return -1;
1900 }
1901 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1902 (int)ld.ld_symb_size, strtab) < 0)
1903 goto err;
1904
1905#if 0
1906 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1907 fprintf(stderr, "[symbol: %s]\n", cp);
1908 cp += strlen(cp)+1;
1909 }
1910 return 0;
1911#endif
1912 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1913 if (strcmp(cp, "_vfork") == 0) {
1914 if (debug)
1915 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1916 strcpy(cp, "_fork");
1917 break;
1918 }
1919 cp += strlen(cp)+1;
1920 }
1921 if (cp < strtab + ld.ld_symb_size)
1922 /*
1923 * Write entire symbol table back to avoid
1924 * memory alignment bugs in ptrace
1925 */
1926 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1927 (int)ld.ld_symb_size, strtab) < 0)
1928 goto err;
1929
1930 free(strtab);
1931 return 0;
1932
1933err:
1934 free(strtab);
1935 return -1;
1936}
1937
1938#endif /* SUNOS4 */