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