blob: a3cde446cd025d2ffd4095c647789308c4259da0 [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 McGrathac971c22003-03-31 01:03:33 +00001226# elif defined (SH)
1227# define arg0_offset (4*(REG_REG0+4))
1228# define arg1_offset (4*(REG_REG0+5))
Roland McGrathd81f1d92003-01-09 06:53:34 +00001229# else
1230# define arg0_offset 0
1231# define arg1_offset 4
Roland McGrathac971c22003-03-31 01:03:33 +00001232# if defined ARM
Roland McGrathe1df47f2003-01-14 09:46:15 +00001233# define restore_arg0(tcp, state, val) 0
1234# endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001235# endif
1236
1237typedef int arg_setup_state;
1238
1239# define arg_setup(tcp, state) (0)
1240# define arg_finish_change(tcp, state) 0
1241# define get_arg0(tcp, cookie, valp) \
1242 (upeek ((tcp)->pid, arg0_offset, (valp)))
1243# define get_arg1(tcp, cookie, valp) \
1244 (upeek ((tcp)->pid, arg1_offset, (valp)))
1245
1246static int
1247set_arg0 (struct tcb *tcp, void *cookie, long val)
1248{
1249 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1250}
1251
1252static int
1253set_arg1 (struct tcb *tcp, void *cookie, long val)
1254{
1255 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1256}
1257
1258#endif
1259
Roland McGrathe1df47f2003-01-14 09:46:15 +00001260#ifndef restore_arg0
1261# define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1262#endif
1263#ifndef restore_arg1
1264# define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1265#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001266
1267int
1268setbpt(tcp)
1269struct tcb *tcp;
1270{
1271 extern int change_syscall(struct tcb *, int);
1272 arg_setup_state state;
1273
1274 if (tcp->flags & TCB_BPTSET) {
1275 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1276 return -1;
1277 }
1278
1279 switch (tcp->scno) {
Roland McGrath9383c6c2003-01-18 00:19:31 +00001280#ifdef SYS_vfork
1281 case SYS_vfork:
1282#endif
Roland McGrathd81f1d92003-01-09 06:53:34 +00001283#ifdef SYS_fork
1284 case SYS_fork:
Roland McGrath9b0982b2003-01-18 00:21:51 +00001285#endif
1286#if defined SYS_fork || defined SYS_vfork
Roland McGrathd81f1d92003-01-09 06:53:34 +00001287 if (arg_setup (tcp, &state) < 0
1288 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1289 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1290 || change_syscall(tcp, SYS_clone) < 0
1291 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1292 || set_arg1 (tcp, &state, 0) < 0
1293 || arg_finish_change (tcp, &state) < 0)
1294 return -1;
1295 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1296 tcp->u_arg[1] = 0;
1297 tcp->flags |= TCB_BPTSET;
1298 return 0;
1299#endif
1300
1301 case SYS_clone:
1302#ifdef SYS_clone2
1303 case SYS_clone2:
1304#endif
1305 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1306 && (arg_setup (tcp, &state) < 0
1307 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1308 || arg_finish_change (tcp, &state) < 0))
1309 return -1;
1310 tcp->flags |= TCB_BPTSET;
1311 tcp->inst[0] = tcp->u_arg[0];
1312 tcp->inst[1] = tcp->u_arg[1];
1313 return 0;
1314
1315 default:
1316 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1317 tcp->scno, tcp->pid);
1318 break;
1319 }
1320
1321 return -1;
1322}
1323
1324int
1325clearbpt(tcp)
1326struct tcb *tcp;
1327{
1328 arg_setup_state state;
1329 if (arg_setup (tcp, &state) < 0
Roland McGrathe1df47f2003-01-14 09:46:15 +00001330 || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1331 || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
Roland McGrathd81f1d92003-01-09 06:53:34 +00001332 || arg_finish_change (tcp, &state))
1333 return -1;
1334 tcp->flags &= ~TCB_BPTSET;
1335 return 0;
1336}
1337
1338#else
1339
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001340int
1341setbpt(tcp)
1342struct tcb *tcp;
1343{
1344
1345#ifdef LINUX
1346#ifdef SPARC
1347 /* We simply use the SunOS breakpoint code. */
1348
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001349 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001350#define LOOPA 0x30800000 /* ba,a 0 */
1351
1352 if (tcp->flags & TCB_BPTSET) {
1353 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1354 return -1;
1355 }
1356 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1357 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1358 return -1;
1359 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001360 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001361 errno = 0;
1362 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1363 if(errno) {
1364 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1365 return -1;
1366 }
1367
1368 /*
1369 * XXX - BRUTAL MODE ON
1370 * We cannot set a real BPT in the child, since it will not be
1371 * traced at the moment it will reach the trap and would probably
1372 * die with a core dump.
1373 * Thus, we are force our way in by taking out two instructions
1374 * and insert an eternal loop instead, in expectance of the SIGSTOP
1375 * generated by out PTRACE_ATTACH.
1376 * Of cause, if we evaporate ourselves in the middle of all this...
1377 */
1378 errno = 0;
1379 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1380 if(errno) {
1381 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1382 return -1;
1383 }
1384 tcp->flags |= TCB_BPTSET;
1385
1386#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001387#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001388 if (ia32) {
1389# define LOOP 0x0000feeb
1390 if (tcp->flags & TCB_BPTSET) {
1391 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1392 tcp->pid);
1393 return -1;
1394 }
1395 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1396 return -1;
1397 if (debug)
1398 fprintf(stderr, "[%d] setting bpt at %lx\n",
1399 tcp->pid, tcp->baddr);
1400 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1401 (char *) tcp->baddr, 0);
1402 if (errno) {
1403 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1404 return -1;
1405 }
1406 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1407 if (errno) {
1408 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1409 return -1;
1410 }
1411 tcp->flags |= TCB_BPTSET;
1412 } else {
1413 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001414 * Our strategy here is to replace the bundle that
1415 * contained the clone() syscall with a bundle of the
1416 * form:
1417 *
1418 * { 1: br 1b; br 1b; br 1b }
1419 *
1420 * This ensures that the newly forked child will loop
1421 * endlessly until we've got a chance to attach to it.
1422 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001423# define LOOP0 0x0000100000000017
1424# define LOOP1 0x4000000000200000
1425 unsigned long addr, ipsr;
1426 pid_t pid;
1427
1428 pid = tcp->pid;
1429 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1430 return -1;
1431 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1432 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001433 /* store "ri" in low two bits */
1434 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001435
1436 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001437 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1438 0);
1439 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1440 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001441 if (errno) {
1442 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1443 return -1;
1444 }
1445
1446 errno = 0;
1447 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1448 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1449 if (errno) {
1450 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1451 return -1;
1452 }
1453 tcp->flags |= TCB_BPTSET;
1454 }
1455#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456
Michal Ludvig0e035502002-09-23 15:41:01 +00001457#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001458#define LOOP 0x0000feeb
1459#elif defined (M68K)
1460#define LOOP 0x60fe0000
1461#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001462#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001463#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001464#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001465#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001466#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001467#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001468#define LOOP 0x1000ffff
1469#elif defined(S390)
1470#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001471#elif defined(S390X)
1472#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001473#elif defined(HPPA)
1474#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001475#elif defined(SH)
1476#ifdef __LITTLE_ENDIAN__
1477#define LOOP 0x0000affe
1478#else
1479#define LOOP 0xfeaf0000
1480#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001481#else
1482#error unknown architecture
1483#endif
1484
1485 if (tcp->flags & TCB_BPTSET) {
1486 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1487 return -1;
1488 }
1489#if defined (I386)
1490 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1491 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001492#elif defined (X86_64)
1493 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1494 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495#elif defined (M68K)
1496 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1497 return -1;
1498#elif defined (ALPHA)
1499 return -1;
1500#elif defined (ARM)
1501 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001502#elif defined (MIPS)
1503 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001505 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001506 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001507#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001508 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1509 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001510#elif defined(HPPA)
1511 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1512 return -1;
1513 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001514#elif defined(SH)
1515 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1516 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517#else
1518#error unknown architecture
1519#endif
1520 if (debug)
1521 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1522 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1523 if (errno) {
1524 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1525 return -1;
1526 }
1527 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1528 if (errno) {
1529 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1530 return -1;
1531 }
1532 tcp->flags |= TCB_BPTSET;
1533
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001534#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001535#endif /* SPARC */
1536#endif /* LINUX */
1537
1538#ifdef SUNOS4
1539#ifdef SPARC /* This code is slightly sparc specific */
1540
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001541 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001542#define BPT 0x91d02001 /* ta 1 */
1543#define LOOP 0x10800000 /* ba 0 */
1544#define LOOPA 0x30800000 /* ba,a 0 */
1545#define NOP 0x01000000
1546#if LOOPA
1547 static int loopdeloop[1] = {LOOPA};
1548#else
1549 static int loopdeloop[2] = {LOOP, NOP};
1550#endif
1551
1552 if (tcp->flags & TCB_BPTSET) {
1553 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1554 return -1;
1555 }
1556 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1557 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1558 return -1;
1559 }
1560 tcp->baddr = regs.r_o7 + 8;
1561 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1562 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1563 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1564 return -1;
1565 }
1566
1567 /*
1568 * XXX - BRUTAL MODE ON
1569 * We cannot set a real BPT in the child, since it will not be
1570 * traced at the moment it will reach the trap and would probably
1571 * die with a core dump.
1572 * Thus, we are force our way in by taking out two instructions
1573 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1574 * generated by out PTRACE_ATTACH.
1575 * Of cause, if we evaporate ourselves in the middle of all this...
1576 */
1577 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1578 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1579 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1580 return -1;
1581 }
1582 tcp->flags |= TCB_BPTSET;
1583
1584#endif /* SPARC */
1585#endif /* SUNOS4 */
1586
1587 return 0;
1588}
1589
1590int
1591clearbpt(tcp)
1592struct tcb *tcp;
1593{
1594
1595#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001596#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001598#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001600#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001601 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001602#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001604#elif defined(HPPA)
1605 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001606#elif defined(SH)
1607 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001608#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609
1610#ifdef SPARC
1611 /* Again, we borrow the SunOS breakpoint code. */
1612 if (!(tcp->flags & TCB_BPTSET)) {
1613 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1614 return -1;
1615 }
1616 errno = 0;
1617 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1618 if(errno) {
1619 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1620 return -1;
1621 }
1622 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001623#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001624 if (ia32) {
1625 unsigned long addr;
1626
1627 if (debug)
1628 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1629 if (!(tcp->flags & TCB_BPTSET)) {
1630 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1631 return -1;
1632 }
1633 errno = 0;
1634 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1635 if (errno) {
1636 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1637 return -1;
1638 }
1639 tcp->flags &= ~TCB_BPTSET;
1640
1641 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1642 return -1;
1643 if (addr != tcp->baddr) {
1644 /* The breakpoint has not been reached yet. */
1645 if (debug)
1646 fprintf(stderr,
1647 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1648 addr, tcp->baddr);
1649 return 0;
1650 }
1651 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001652 unsigned long addr, ipsr;
1653 pid_t pid;
1654
1655 pid = tcp->pid;
1656
1657 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1658 return -1;
1659 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1660 return -1;
1661
1662 /* restore original bundle: */
1663 errno = 0;
1664 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1665 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1666 if (errno) {
1667 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1668 return -1;
1669 }
1670
1671 /* restore original "ri" in ipsr: */
1672 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1673 errno = 0;
1674 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1675 if (errno) {
1676 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1677 return -1;
1678 }
1679
1680 tcp->flags &= ~TCB_BPTSET;
1681
1682 if (addr != (tcp->baddr & ~0x3)) {
1683 /* the breakpoint has not been reached yet. */
1684 if (debug)
1685 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1686 addr, tcp->baddr);
1687 return 0;
1688 }
1689 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001690#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691
1692 if (debug)
1693 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1694 if (!(tcp->flags & TCB_BPTSET)) {
1695 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1696 return -1;
1697 }
1698 errno = 0;
1699 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1700 if (errno) {
1701 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1702 return -1;
1703 }
1704 tcp->flags &= ~TCB_BPTSET;
1705
1706#ifdef I386
1707 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1708 return -1;
1709 if (eip != tcp->baddr) {
1710 /* The breakpoint has not been reached yet. */
1711 if (debug)
1712 fprintf(stderr,
1713 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1714 eip, tcp->baddr);
1715 return 0;
1716 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001717#elif defined(X86_64)
1718 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1719 return -1;
1720 if (eip != tcp->baddr) {
1721 /* The breakpoint has not been reached yet. */
1722 if (debug)
1723 fprintf(stderr,
1724 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1725 eip, tcp->baddr);
1726 return 0;
1727 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001728#elif defined(POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +00001729 if (upeek(tcp->pid, sizeof(unsigned long)*PT_NIP, &pc) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730 return -1;
1731 if (pc != tcp->baddr) {
1732 /* The breakpoint has not been reached yet. */
1733 if (debug)
1734 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1735 pc, tcp->baddr);
1736 return 0;
1737 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001738#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001739 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1740 return -1;
1741 if (pc != tcp->baddr) {
1742 /* The breakpoint has not been reached yet. */
1743 if (debug)
1744 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1745 pc, tcp->baddr);
1746 return 0;
1747 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001748#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001749 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1750 return -1;
1751 if (pc != tcp->baddr) {
1752 /* The breakpoint has not been reached yet. */
1753 if (debug)
1754 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1755 pc, tcp->baddr);
1756 return 0;
1757 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001758#elif defined(HPPA)
1759 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1760 return -1;
1761 iaoq &= ~0x03;
1762 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1763 /* The breakpoint has not been reached yet. */
1764 if (debug)
1765 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1766 iaoq, tcp->baddr);
1767 return 0;
1768 }
1769 iaoq = tcp->baddr | 3;
1770 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1771 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1772 * has no significant effect.
1773 */
1774 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1775 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001776#elif defined(SH)
1777 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1778 return -1;
1779 if (pc != tcp->baddr) {
1780 /* The breakpoint has not been reached yet. */
1781 if (debug)
1782 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1783 pc, tcp->baddr);
1784 return 0;
1785 }
1786
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001787#endif /* arch */
1788#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789#endif /* LINUX */
1790
1791#ifdef SUNOS4
1792#ifdef SPARC
1793
1794#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001795 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796#endif
1797
1798 if (!(tcp->flags & TCB_BPTSET)) {
1799 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1800 return -1;
1801 }
1802 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1803 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1804 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1805 return -1;
1806 }
1807 tcp->flags &= ~TCB_BPTSET;
1808
1809#if !LOOPA
1810 /*
1811 * Since we don't have a single instruction breakpoint, we may have
1812 * to adjust the program counter after removing the our `breakpoint'.
1813 */
1814 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1815 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1816 return -1;
1817 }
1818 if ((regs.r_pc < tcp->baddr) ||
1819 (regs.r_pc > tcp->baddr + 4)) {
1820 /* The breakpoint has not been reached yet */
1821 if (debug)
1822 fprintf(stderr,
1823 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1824 regs.r_pc, tcp->parent->baddr);
1825 return 0;
1826 }
1827 if (regs.r_pc != tcp->baddr)
1828 if (debug)
1829 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1830 regs.r_pc, tcp->baddr);
1831
1832 regs.r_pc = tcp->baddr;
1833 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1834 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1835 return -1;
1836 }
1837#endif /* LOOPA */
1838#endif /* SPARC */
1839#endif /* SUNOS4 */
1840
1841 return 0;
1842}
1843
Roland McGrathd81f1d92003-01-09 06:53:34 +00001844#endif
1845
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001846#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001847
1848#ifdef SUNOS4
1849
1850static int
1851getex(pid, hdr)
1852int pid;
1853struct exec *hdr;
1854{
1855 int n;
1856
1857 for (n = 0; n < sizeof *hdr; n += 4) {
1858 long res;
1859 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1860 return -1;
1861 memcpy(((char *) hdr) + n, &res, 4);
1862 }
1863 if (debug) {
1864 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1865 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1866 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1867 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1868 }
1869 return 0;
1870}
1871
1872int
1873fixvfork(tcp)
1874struct tcb *tcp;
1875{
1876 int pid = tcp->pid;
1877 /*
1878 * Change `vfork' in a freshly exec'ed dynamically linked
1879 * executable's (internal) symbol table to plain old `fork'
1880 */
1881
1882 struct exec hdr;
1883 struct link_dynamic dyn;
1884 struct link_dynamic_2 ld;
1885 char *strtab, *cp;
1886
1887 if (getex(pid, &hdr) < 0)
1888 return -1;
1889 if (!hdr.a_dynamic)
1890 return -1;
1891
1892 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1893 fprintf(stderr, "Cannot read DYNAMIC\n");
1894 return -1;
1895 }
1896 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1897 fprintf(stderr, "Cannot read link_dynamic_2\n");
1898 return -1;
1899 }
1900 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1901 fprintf(stderr, "fixvfork: out of memory\n");
1902 return -1;
1903 }
1904 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1905 (int)ld.ld_symb_size, strtab) < 0)
1906 goto err;
1907
1908#if 0
1909 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1910 fprintf(stderr, "[symbol: %s]\n", cp);
1911 cp += strlen(cp)+1;
1912 }
1913 return 0;
1914#endif
1915 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1916 if (strcmp(cp, "_vfork") == 0) {
1917 if (debug)
1918 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1919 strcpy(cp, "_fork");
1920 break;
1921 }
1922 cp += strlen(cp)+1;
1923 }
1924 if (cp < strtab + ld.ld_symb_size)
1925 /*
1926 * Write entire symbol table back to avoid
1927 * memory alignment bugs in ptrace
1928 */
1929 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1930 (int)ld.ld_symb_size, strtab) < 0)
1931 goto err;
1932
1933 free(strtab);
1934 return 0;
1935
1936err:
1937 free(strtab);
1938 return -1;
1939}
1940
1941#endif /* SUNOS4 */