blob: 675fcb1df6dfae9f1edac7f4b1842e35c8aee047 [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)
1203# define arg0_offset (4*PT_ORIG_R3)
1204# define arg1_offset (4*(1+PT_R3))
1205# elif defined (HPPA)
1206# define arg0_offset PT_GR26
1207# define arg1_offset (PT_GR26-4)
1208# else
1209# define arg0_offset 0
1210# define arg1_offset 4
1211# endif
1212
1213typedef int arg_setup_state;
1214
1215# define arg_setup(tcp, state) (0)
1216# define arg_finish_change(tcp, state) 0
1217# define get_arg0(tcp, cookie, valp) \
1218 (upeek ((tcp)->pid, arg0_offset, (valp)))
1219# define get_arg1(tcp, cookie, valp) \
1220 (upeek ((tcp)->pid, arg1_offset, (valp)))
1221
1222static int
1223set_arg0 (struct tcb *tcp, void *cookie, long val)
1224{
1225 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1226}
1227
1228static int
1229set_arg1 (struct tcb *tcp, void *cookie, long val)
1230{
1231 return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1232}
1233
1234#endif
1235
1236
1237int
1238setbpt(tcp)
1239struct tcb *tcp;
1240{
1241 extern int change_syscall(struct tcb *, int);
1242 arg_setup_state state;
1243
1244 if (tcp->flags & TCB_BPTSET) {
1245 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1246 return -1;
1247 }
1248
1249 switch (tcp->scno) {
1250#ifdef SYS_fork
1251 case SYS_fork:
1252 if (arg_setup (tcp, &state) < 0
1253 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1254 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1255 || change_syscall(tcp, SYS_clone) < 0
1256 || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1257 || set_arg1 (tcp, &state, 0) < 0
1258 || arg_finish_change (tcp, &state) < 0)
1259 return -1;
1260 tcp->u_arg[0] = CLONE_PTRACE|SIGCHLD;
1261 tcp->u_arg[1] = 0;
1262 tcp->flags |= TCB_BPTSET;
1263 return 0;
1264#endif
1265
1266 case SYS_clone:
1267#ifdef SYS_clone2
1268 case SYS_clone2:
1269#endif
1270 if ((tcp->u_arg[0] & CLONE_PTRACE) == 0
1271 && (arg_setup (tcp, &state) < 0
1272 || set_arg0 (tcp, &state, tcp->u_arg[0] | CLONE_PTRACE) < 0
1273 || arg_finish_change (tcp, &state) < 0))
1274 return -1;
1275 tcp->flags |= TCB_BPTSET;
1276 tcp->inst[0] = tcp->u_arg[0];
1277 tcp->inst[1] = tcp->u_arg[1];
1278 return 0;
1279
1280 default:
1281 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1282 tcp->scno, tcp->pid);
1283 break;
1284 }
1285
1286 return -1;
1287}
1288
1289int
1290clearbpt(tcp)
1291struct tcb *tcp;
1292{
1293 arg_setup_state state;
1294 if (arg_setup (tcp, &state) < 0
1295 || set_arg0 (tcp, &state, tcp->inst[0]) < 0
1296 || set_arg1 (tcp, &state, tcp->inst[1]) < 0
1297 || arg_finish_change (tcp, &state))
1298 return -1;
1299 tcp->flags &= ~TCB_BPTSET;
1300 return 0;
1301}
1302
1303#else
1304
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305int
1306setbpt(tcp)
1307struct tcb *tcp;
1308{
1309
1310#ifdef LINUX
1311#ifdef SPARC
1312 /* We simply use the SunOS breakpoint code. */
1313
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001314 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315#define LOOPA 0x30800000 /* ba,a 0 */
1316
1317 if (tcp->flags & TCB_BPTSET) {
1318 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1319 return -1;
1320 }
1321 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1322 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1323 return -1;
1324 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001325 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001326 errno = 0;
1327 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1328 if(errno) {
1329 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1330 return -1;
1331 }
1332
1333 /*
1334 * XXX - BRUTAL MODE ON
1335 * We cannot set a real BPT in the child, since it will not be
1336 * traced at the moment it will reach the trap and would probably
1337 * die with a core dump.
1338 * Thus, we are force our way in by taking out two instructions
1339 * and insert an eternal loop instead, in expectance of the SIGSTOP
1340 * generated by out PTRACE_ATTACH.
1341 * Of cause, if we evaporate ourselves in the middle of all this...
1342 */
1343 errno = 0;
1344 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1345 if(errno) {
1346 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1347 return -1;
1348 }
1349 tcp->flags |= TCB_BPTSET;
1350
1351#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001352#ifdef IA64
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001353 if (ia32) {
1354# define LOOP 0x0000feeb
1355 if (tcp->flags & TCB_BPTSET) {
1356 fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1357 tcp->pid);
1358 return -1;
1359 }
1360 if (upeek(tcp->pid, PT_CR_IIP, &tcp->baddr) < 0)
1361 return -1;
1362 if (debug)
1363 fprintf(stderr, "[%d] setting bpt at %lx\n",
1364 tcp->pid, tcp->baddr);
1365 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1366 (char *) tcp->baddr, 0);
1367 if (errno) {
1368 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1369 return -1;
1370 }
1371 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1372 if (errno) {
1373 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1374 return -1;
1375 }
1376 tcp->flags |= TCB_BPTSET;
1377 } else {
1378 /*
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001379 * Our strategy here is to replace the bundle that
1380 * contained the clone() syscall with a bundle of the
1381 * form:
1382 *
1383 * { 1: br 1b; br 1b; br 1b }
1384 *
1385 * This ensures that the newly forked child will loop
1386 * endlessly until we've got a chance to attach to it.
1387 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001388# define LOOP0 0x0000100000000017
1389# define LOOP1 0x4000000000200000
1390 unsigned long addr, ipsr;
1391 pid_t pid;
1392
1393 pid = tcp->pid;
1394 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1395 return -1;
1396 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1397 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001398 /* store "ri" in low two bits */
1399 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001400
1401 errno = 0;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001402 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1403 0);
1404 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1405 0);
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001406 if (errno) {
1407 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1408 return -1;
1409 }
1410
1411 errno = 0;
1412 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1413 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1414 if (errno) {
1415 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1416 return -1;
1417 }
1418 tcp->flags |= TCB_BPTSET;
1419 }
1420#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421
Michal Ludvig0e035502002-09-23 15:41:01 +00001422#if defined (I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423#define LOOP 0x0000feeb
1424#elif defined (M68K)
1425#define LOOP 0x60fe0000
1426#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001427#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428#elif defined (POWERPC)
Roland McGrath1e85cf92002-12-16 20:40:54 +00001429#define LOOP 0x48000000
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001431#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001432#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001433#define LOOP 0x1000ffff
1434#elif defined(S390)
1435#define LOOP 0xa7f40000 /* BRC 15,0 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001436#elif defined(S390X)
1437#define LOOP 0xa7f4000000000000UL /* BRC 15,0 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001438#elif defined(HPPA)
1439#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001440#elif defined(SH)
1441#ifdef __LITTLE_ENDIAN__
1442#define LOOP 0x0000affe
1443#else
1444#define LOOP 0xfeaf0000
1445#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446#else
1447#error unknown architecture
1448#endif
1449
1450 if (tcp->flags & TCB_BPTSET) {
1451 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1452 return -1;
1453 }
1454#if defined (I386)
1455 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1456 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00001457#elif defined (X86_64)
1458 if (upeek(tcp->pid, 8*RIP, &tcp->baddr) < 0)
1459 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001460#elif defined (M68K)
1461 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1462 return -1;
1463#elif defined (ALPHA)
1464 return -1;
1465#elif defined (ARM)
1466 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001467#elif defined (MIPS)
1468 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001469#elif defined (POWERPC)
1470 if (upeek(tcp->pid, 4*PT_NIP, &tcp->baddr) < 0)
1471 return -1;
Michal Ludvig10a88d02002-10-07 14:31:00 +00001472#elif defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001473 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1474 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001475#elif defined(HPPA)
1476 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)
1477 return -1;
1478 tcp->baddr &= ~0x03;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001479#elif defined(SH)
1480 if (upeek(tcp->pid, 4*REG_PC, &tcp->baddr) < 0)
1481 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482#else
1483#error unknown architecture
1484#endif
1485 if (debug)
1486 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1487 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1488 if (errno) {
1489 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1490 return -1;
1491 }
1492 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1493 if (errno) {
1494 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1495 return -1;
1496 }
1497 tcp->flags |= TCB_BPTSET;
1498
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001499#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500#endif /* SPARC */
1501#endif /* LINUX */
1502
1503#ifdef SUNOS4
1504#ifdef SPARC /* This code is slightly sparc specific */
1505
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001506 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507#define BPT 0x91d02001 /* ta 1 */
1508#define LOOP 0x10800000 /* ba 0 */
1509#define LOOPA 0x30800000 /* ba,a 0 */
1510#define NOP 0x01000000
1511#if LOOPA
1512 static int loopdeloop[1] = {LOOPA};
1513#else
1514 static int loopdeloop[2] = {LOOP, NOP};
1515#endif
1516
1517 if (tcp->flags & TCB_BPTSET) {
1518 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1519 return -1;
1520 }
1521 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1522 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1523 return -1;
1524 }
1525 tcp->baddr = regs.r_o7 + 8;
1526 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1527 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1528 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1529 return -1;
1530 }
1531
1532 /*
1533 * XXX - BRUTAL MODE ON
1534 * We cannot set a real BPT in the child, since it will not be
1535 * traced at the moment it will reach the trap and would probably
1536 * die with a core dump.
1537 * Thus, we are force our way in by taking out two instructions
1538 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1539 * generated by out PTRACE_ATTACH.
1540 * Of cause, if we evaporate ourselves in the middle of all this...
1541 */
1542 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1543 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1544 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1545 return -1;
1546 }
1547 tcp->flags |= TCB_BPTSET;
1548
1549#endif /* SPARC */
1550#endif /* SUNOS4 */
1551
1552 return 0;
1553}
1554
1555int
1556clearbpt(tcp)
1557struct tcb *tcp;
1558{
1559
1560#ifdef LINUX
Michal Ludvig0e035502002-09-23 15:41:01 +00001561#if defined(I386) || defined(X86_64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562 long eip;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001563#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001565#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001567#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001568 long pc;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001569#elif defined(HPPA)
1570 long iaoq;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001571#elif defined(SH)
1572 long pc;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001573#endif /* architecture */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574
1575#ifdef SPARC
1576 /* Again, we borrow the SunOS breakpoint code. */
1577 if (!(tcp->flags & TCB_BPTSET)) {
1578 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1579 return -1;
1580 }
1581 errno = 0;
1582 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1583 if(errno) {
1584 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1585 return -1;
1586 }
1587 tcp->flags &= ~TCB_BPTSET;
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001588#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001589 if (ia32) {
1590 unsigned long addr;
1591
1592 if (debug)
1593 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1594 if (!(tcp->flags & TCB_BPTSET)) {
1595 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1596 return -1;
1597 }
1598 errno = 0;
1599 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1600 if (errno) {
1601 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1602 return -1;
1603 }
1604 tcp->flags &= ~TCB_BPTSET;
1605
1606 if (upeek(tcp->pid, PT_CR_IIP, &addr) < 0)
1607 return -1;
1608 if (addr != tcp->baddr) {
1609 /* The breakpoint has not been reached yet. */
1610 if (debug)
1611 fprintf(stderr,
1612 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1613 addr, tcp->baddr);
1614 return 0;
1615 }
1616 } else {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001617 unsigned long addr, ipsr;
1618 pid_t pid;
1619
1620 pid = tcp->pid;
1621
1622 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1623 return -1;
1624 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1625 return -1;
1626
1627 /* restore original bundle: */
1628 errno = 0;
1629 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1630 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1631 if (errno) {
1632 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1633 return -1;
1634 }
1635
1636 /* restore original "ri" in ipsr: */
1637 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1638 errno = 0;
1639 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1640 if (errno) {
1641 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1642 return -1;
1643 }
1644
1645 tcp->flags &= ~TCB_BPTSET;
1646
1647 if (addr != (tcp->baddr & ~0x3)) {
1648 /* the breakpoint has not been reached yet. */
1649 if (debug)
1650 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1651 addr, tcp->baddr);
1652 return 0;
1653 }
1654 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001655#else /* !IA64 && ! SPARC */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001656
1657 if (debug)
1658 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1659 if (!(tcp->flags & TCB_BPTSET)) {
1660 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1661 return -1;
1662 }
1663 errno = 0;
1664 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1665 if (errno) {
1666 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1667 return -1;
1668 }
1669 tcp->flags &= ~TCB_BPTSET;
1670
1671#ifdef I386
1672 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1673 return -1;
1674 if (eip != tcp->baddr) {
1675 /* The breakpoint has not been reached yet. */
1676 if (debug)
1677 fprintf(stderr,
1678 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1679 eip, tcp->baddr);
1680 return 0;
1681 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001682#elif defined(X86_64)
1683 if (upeek(tcp->pid, 8*RIP, &eip) < 0)
1684 return -1;
1685 if (eip != tcp->baddr) {
1686 /* The breakpoint has not been reached yet. */
1687 if (debug)
1688 fprintf(stderr,
1689 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1690 eip, tcp->baddr);
1691 return 0;
1692 }
Wichert Akkermanc7926982000-04-10 22:22:31 +00001693#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)
1695 return -1;
1696 if (pc != tcp->baddr) {
1697 /* The breakpoint has not been reached yet. */
1698 if (debug)
1699 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1700 pc, tcp->baddr);
1701 return 0;
1702 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001703#elif defined(M68K)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001704 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1705 return -1;
1706 if (pc != tcp->baddr) {
1707 /* The breakpoint has not been reached yet. */
1708 if (debug)
1709 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1710 pc, tcp->baddr);
1711 return 0;
1712 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001713#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1715 return -1;
1716 if (pc != tcp->baddr) {
1717 /* The breakpoint has not been reached yet. */
1718 if (debug)
1719 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1720 pc, tcp->baddr);
1721 return 0;
1722 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001723#elif defined(HPPA)
1724 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)
1725 return -1;
1726 iaoq &= ~0x03;
1727 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
1728 /* The breakpoint has not been reached yet. */
1729 if (debug)
1730 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
1731 iaoq, tcp->baddr);
1732 return 0;
1733 }
1734 iaoq = tcp->baddr | 3;
1735 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
1736 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
1737 * has no significant effect.
1738 */
1739 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
1740 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
Wichert Akkermanccef6372002-05-01 16:39:22 +00001741#elif defined(SH)
1742 if (upeek(tcp->pid, 4*REG_PC, &pc) < 0)
1743 return -1;
1744 if (pc != tcp->baddr) {
1745 /* The breakpoint has not been reached yet. */
1746 if (debug)
1747 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1748 pc, tcp->baddr);
1749 return 0;
1750 }
1751
Wichert Akkermanfaf72222000-02-19 23:59:03 +00001752#endif /* arch */
1753#endif /* !SPARC && !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001754#endif /* LINUX */
1755
1756#ifdef SUNOS4
1757#ifdef SPARC
1758
1759#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001760 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001761#endif
1762
1763 if (!(tcp->flags & TCB_BPTSET)) {
1764 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1765 return -1;
1766 }
1767 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1768 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1769 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1770 return -1;
1771 }
1772 tcp->flags &= ~TCB_BPTSET;
1773
1774#if !LOOPA
1775 /*
1776 * Since we don't have a single instruction breakpoint, we may have
1777 * to adjust the program counter after removing the our `breakpoint'.
1778 */
1779 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1780 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1781 return -1;
1782 }
1783 if ((regs.r_pc < tcp->baddr) ||
1784 (regs.r_pc > tcp->baddr + 4)) {
1785 /* The breakpoint has not been reached yet */
1786 if (debug)
1787 fprintf(stderr,
1788 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1789 regs.r_pc, tcp->parent->baddr);
1790 return 0;
1791 }
1792 if (regs.r_pc != tcp->baddr)
1793 if (debug)
1794 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1795 regs.r_pc, tcp->baddr);
1796
1797 regs.r_pc = tcp->baddr;
1798 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1799 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1800 return -1;
1801 }
1802#endif /* LOOPA */
1803#endif /* SPARC */
1804#endif /* SUNOS4 */
1805
1806 return 0;
1807}
1808
Roland McGrathd81f1d92003-01-09 06:53:34 +00001809#endif
1810
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001811#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001812
1813#ifdef SUNOS4
1814
1815static int
1816getex(pid, hdr)
1817int pid;
1818struct exec *hdr;
1819{
1820 int n;
1821
1822 for (n = 0; n < sizeof *hdr; n += 4) {
1823 long res;
1824 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1825 return -1;
1826 memcpy(((char *) hdr) + n, &res, 4);
1827 }
1828 if (debug) {
1829 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1830 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1831 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1832 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1833 }
1834 return 0;
1835}
1836
1837int
1838fixvfork(tcp)
1839struct tcb *tcp;
1840{
1841 int pid = tcp->pid;
1842 /*
1843 * Change `vfork' in a freshly exec'ed dynamically linked
1844 * executable's (internal) symbol table to plain old `fork'
1845 */
1846
1847 struct exec hdr;
1848 struct link_dynamic dyn;
1849 struct link_dynamic_2 ld;
1850 char *strtab, *cp;
1851
1852 if (getex(pid, &hdr) < 0)
1853 return -1;
1854 if (!hdr.a_dynamic)
1855 return -1;
1856
1857 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1858 fprintf(stderr, "Cannot read DYNAMIC\n");
1859 return -1;
1860 }
1861 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1862 fprintf(stderr, "Cannot read link_dynamic_2\n");
1863 return -1;
1864 }
1865 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1866 fprintf(stderr, "fixvfork: out of memory\n");
1867 return -1;
1868 }
1869 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1870 (int)ld.ld_symb_size, strtab) < 0)
1871 goto err;
1872
1873#if 0
1874 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1875 fprintf(stderr, "[symbol: %s]\n", cp);
1876 cp += strlen(cp)+1;
1877 }
1878 return 0;
1879#endif
1880 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1881 if (strcmp(cp, "_vfork") == 0) {
1882 if (debug)
1883 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1884 strcpy(cp, "_fork");
1885 break;
1886 }
1887 cp += strlen(cp)+1;
1888 }
1889 if (cp < strtab + ld.ld_symb_size)
1890 /*
1891 * Write entire symbol table back to avoid
1892 * memory alignment bugs in ptrace
1893 */
1894 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1895 (int)ld.ld_symb_size, strtab) < 0)
1896 goto err;
1897
1898 free(strtab);
1899 return 0;
1900
1901err:
1902 free(strtab);
1903 return -1;
1904}
1905
1906#endif /* SUNOS4 */