blob: b69739e37fc3dd6747e7889d51188aeec8464ed7 [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
38#include <sys/user.h>
39#include <sys/param.h>
40#include <fcntl.h>
41#ifdef SUNOS4
42#include <machine/reg.h>
43#include <a.out.h>
44#include <link.h>
45#endif /* SUNOS4 */
Wichert Akkerman36915a11999-07-13 15:45:02 +000046
Wichert Akkerman15dea971999-10-06 13:06:34 +000047#if defined(linux)
Wichert Akkerman36915a11999-07-13 15:45:02 +000048#include <linux/ptrace.h>
49#endif
50
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000051#if defined(LINUX) && defined(IA64)
52#include <asm/ptrace_offsets.h>
53#endif
54
Wichert Akkerman36915a11999-07-13 15:45:02 +000055#ifdef HAVE_SYS_REG_H
56#include <sys/reg.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000057# define PTRACE_PEEKUSR PTRACE_PEEKUSER
58#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000059
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000060#ifdef HAVE_SYS_PTRACE_H
61#include <sys/ptrace.h>
62#endif
63
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000064#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
65#include <sys/utsname.h>
66#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
67
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000068#if defined(LINUX) && defined(SPARC)
69
70#include <asm/reg.h>
71
72#if !defined(__GLIBC__)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073
74#include <linux/unistd.h>
75
76#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\
77 type5,arg5,syscall) \
78type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
79{ \
80 long __res; \
81\
82__asm__ volatile ("or %%g0, %1, %%o0\n\t" \
83 "or %%g0, %2, %%o1\n\t" \
84 "or %%g0, %3, %%o2\n\t" \
85 "or %%g0, %4, %%o3\n\t" \
86 "or %%g0, %5, %%o4\n\t" \
87 "or %%g0, %6, %%g1\n\t" \
88 "t 0x10\n\t" \
89 "bcc 1f\n\t" \
90 "or %%g0, %%o0, %0\n\t" \
91 "sub %%g0, %%o0, %0\n\t" \
92 "1:\n\t" \
93 : "=r" (__res) \
94 : "0" ((long)(arg1)),"1" ((long)(arg2)), \
95 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \
96 "i" (__NR_##syscall) \
97 : "g1", "o0", "o1", "o2", "o3", "o4"); \
98if (__res>=0) \
99 return (type) __res; \
100errno = -__res; \
101return -1; \
102}
103
104static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace)
105
106#define _ptrace
107
108#endif
109
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000110#endif
111
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112/* macros */
113#ifndef MAX
114#define MAX(a,b) (((a) > (b)) ? (a) : (b))
115#endif
116#ifndef MIN
117#define MIN(a,b) (((a) < (b)) ? (a) : (b))
118#endif
119
120void
121tv_tv(tv, a, b)
122struct timeval *tv;
123int a;
124int b;
125{
126 tv->tv_sec = a;
127 tv->tv_usec = b;
128}
129
130int
131tv_nz(a)
132struct timeval *a;
133{
134 return a->tv_sec || a->tv_usec;
135}
136
137int
138tv_cmp(a, b)
139struct timeval *a, *b;
140{
141 if (a->tv_sec < b->tv_sec
142 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
143 return -1;
144 if (a->tv_sec > b->tv_sec
145 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
146 return 1;
147 return 0;
148}
149
150double
151tv_float(tv)
152struct timeval *tv;
153{
154 return tv->tv_sec + tv->tv_usec/1000000.0;
155}
156
157void
158tv_add(tv, a, b)
159struct timeval *tv, *a, *b;
160{
161 tv->tv_sec = a->tv_sec + b->tv_sec;
162 tv->tv_usec = a->tv_usec + b->tv_usec;
163 if (tv->tv_usec > 1000000) {
164 tv->tv_sec++;
165 tv->tv_usec -= 1000000;
166 }
167}
168
169void
170tv_sub(tv, a, b)
171struct timeval *tv, *a, *b;
172{
173 tv->tv_sec = a->tv_sec - b->tv_sec;
174 tv->tv_usec = a->tv_usec - b->tv_usec;
175 if (((long) tv->tv_usec) < 0) {
176 tv->tv_sec--;
177 tv->tv_usec += 1000000;
178 }
179}
180
181void
182tv_div(tv, a, n)
183struct timeval *tv, *a;
184int n;
185{
186 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
187 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
188 tv->tv_usec %= 1000000;
189}
190
191void
192tv_mul(tv, a, n)
193struct timeval *tv, *a;
194int n;
195{
196 tv->tv_usec = a->tv_usec * n;
197 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000;
198 tv->tv_usec %= 1000000;
199}
200
201char *
202xlookup(xlat, val)
203struct xlat *xlat;
204int val;
205{
206 for (; xlat->str != NULL; xlat++)
207 if (xlat->val == val)
208 return xlat->str;
209 return NULL;
210}
211
212/*
213 * Print entry in struct xlat table, if there.
214 */
215void
216printxval(xlat, val, dflt)
217struct xlat *xlat;
218int val;
219char *dflt;
220{
221 char *str = xlookup(xlat, val);
222
223 if (str)
224 tprintf("%s", str);
225 else
226 tprintf("%#x /* %s */", val, dflt);
227}
228
229/*
230 * Interpret `xlat' as an array of flags
231 * print the entries whose bits are on in `flags'
232 * return # of flags printed.
233 */
234int
235addflags(xlat, flags)
236struct xlat *xlat;
237int flags;
238{
239 int n;
240
241 for (n = 0; xlat->str; xlat++) {
242 if (xlat->val && (flags & xlat->val) == xlat->val) {
243 tprintf("|%s", xlat->str);
244 flags &= ~xlat->val;
245 n++;
246 }
247 }
248 if (flags) {
249 tprintf("|%#x", flags);
250 n++;
251 }
252 return n;
253}
254
255int
256printflags(xlat, flags)
257struct xlat *xlat;
258int flags;
259{
260 int n;
261 char *sep;
262
263 if (flags == 0 && xlat->val == 0) {
264 tprintf("%s", xlat->str);
265 return 1;
266 }
267
268 sep = "";
269 for (n = 0; xlat->str; xlat++) {
270 if (xlat->val && (flags & xlat->val) == xlat->val) {
271 tprintf("%s%s", sep, xlat->str);
272 flags &= ~xlat->val;
273 sep = "|";
274 n++;
275 }
276 }
277 if (flags) {
278 tprintf("%s%#x", sep, flags);
279 n++;
280 }
281 return n;
282}
283
284void
285printnum(tcp, addr, fmt)
286struct tcb *tcp;
287long addr;
288char *fmt;
289{
290 int num;
291
292 if (!addr) {
293 tprintf("NULL");
294 return;
295 }
296 if (umove(tcp, addr, &num) < 0) {
297 tprintf("%#lx", addr);
298 return;
299 }
300 tprintf("[");
301 tprintf(fmt, num);
302 tprintf("]");
303}
304
305static char path[MAXPATHLEN + 1];
306
307void
308string_quote(str)
309char *str;
310{
311 char buf[2 * MAXPATHLEN + 1];
312 char *s;
313
314 if (!strpbrk(str, "\"\'\\")) {
315 tprintf("\"%s\"", str);
316 return;
317 }
318 for (s = buf; *str; str++) {
319 switch (*str) {
320 case '\"': case '\'': case '\\':
321 *s++ = '\\'; *s++ = *str; break;
322 default:
323 *s++ = *str; break;
324 }
325 }
326 *s = '\0';
327 tprintf("\"%s\"", buf);
328}
329
330void
331printpath(tcp, addr)
332struct tcb *tcp;
333long addr;
334{
335 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0)
336 tprintf("%#lx", addr);
337 else
338 string_quote(path);
339 return;
340}
341
342void
343printpathn(tcp, addr, n)
344struct tcb *tcp;
345long addr;
346int n;
347{
348 if (umovestr(tcp, addr, n, path) < 0)
349 tprintf("%#lx", addr);
350 else {
351 path[n] = '\0';
352 string_quote(path);
353 }
354}
355
356void
357printstr(tcp, addr, len)
358struct tcb *tcp;
359long addr;
360int len;
361{
362 static unsigned char *str = NULL;
363 static char *outstr;
364 int i, n, c, usehex;
365 char *s, *outend;
366
367 if (!addr) {
368 tprintf("NULL");
369 return;
370 }
371 if (!str) {
372 if ((str = malloc(max_strlen)) == NULL
373 || (outstr = malloc(2*max_strlen)) == NULL) {
374 fprintf(stderr, "printstr: no memory\n");
375 tprintf("%#lx", addr);
376 return;
377 }
378 }
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000379 outend = outstr + max_strlen * 2 - 10;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000380 if (len < 0) {
381 n = max_strlen;
382 if (umovestr(tcp, addr, n, (char *) str) < 0) {
383 tprintf("%#lx", addr);
384 return;
385 }
386 }
387 else {
388 n = MIN(len, max_strlen);
389 if (umoven(tcp, addr, n, (char *) str) < 0) {
390 tprintf("%#lx", addr);
391 return;
392 }
393 }
394
395 usehex = 0;
396 if (xflag > 1)
397 usehex = 1;
398 else if (xflag) {
399 for (i = 0; i < n; i++) {
400 c = str[i];
401 if (len < 0 && c == '\0')
402 break;
403 if (!isprint(c) && !isspace(c)) {
404 usehex = 1;
405 break;
406 }
407 }
408 }
409
410 s = outstr;
411 *s++ = '\"';
412
413 if (usehex) {
414 for (i = 0; i < n; i++) {
415 c = str[i];
416 if (len < 0 && c == '\0')
417 break;
418 sprintf(s, "\\x%02x", c);
419 s += 4;
420 if (s > outend)
421 break;
422 }
423 }
424 else {
425 for (i = 0; i < n; i++) {
426 c = str[i];
427 if (len < 0 && c == '\0')
428 break;
429 switch (c) {
430 case '\"': case '\'': case '\\':
431 *s++ = '\\'; *s++ = c; break;
432 case '\f':
433 *s++ = '\\'; *s++ = 'f'; break;
434 case '\n':
435 *s++ = '\\'; *s++ = 'n'; break;
436 case '\r':
437 *s++ = '\\'; *s++ = 'r'; break;
438 case '\t':
439 *s++ = '\\'; *s++ = 't'; break;
440 case '\v':
441 *s++ = '\\'; *s++ = 'v'; break;
442 default:
443 if (isprint(c))
444 *s++ = c;
445 else if (i < n - 1 && isdigit(str[i + 1])) {
446 sprintf(s, "\\%03o", c);
447 s += 4;
448 }
449 else {
450 sprintf(s, "\\%o", c);
451 s += strlen(s);
452 }
453 break;
454 }
455 if (s > outend)
456 break;
457 }
458 }
459
460 *s++ = '\"';
461 if (i < len || (len < 0 && (i == n || s > outend))) {
462 *s++ = '.'; *s++ = '.'; *s++ = '.';
463 }
464 *s = '\0';
465 tprintf("%s", outstr);
466}
467
468void
469dumpstr(tcp, addr, len)
470struct tcb *tcp;
471long addr;
472int len;
473{
474 static int strsize = -1;
475 static unsigned char *str;
476 static char outstr[80];
477 char *s;
478 int i, j;
479
480 if (strsize < len) {
481 if (str)
482 free(str);
483 if ((str = malloc(len)) == NULL) {
484 fprintf(stderr, "dump: no memory\n");
485 return;
486 }
487 strsize = len;
488 }
489
490 if (umoven(tcp, addr, len, (char *) str) < 0)
491 return;
492
493 for (i = 0; i < len; i += 16) {
494 s = outstr;
495 sprintf(s, " | %05x ", i);
496 s += 9;
497 for (j = 0; j < 16; j++) {
498 if (j == 8)
499 *s++ = ' ';
500 if (i + j < len) {
501 sprintf(s, " %02x", str[i + j]);
502 s += 3;
503 }
504 else {
505 *s++ = ' '; *s++ = ' '; *s++ = ' ';
506 }
507 }
508 *s++ = ' '; *s++ = ' ';
509 for (j = 0; j < 16; j++) {
510 if (j == 8)
511 *s++ = ' ';
512 if (i + j < len) {
513 if (isprint(str[i + j]))
514 *s++ = str[i + j];
515 else
516 *s++ = '.';
517 }
518 else
519 *s++ = ' ';
520 }
521 tprintf("%s |\n", outstr);
522 }
523}
524
525#define PAGMASK (~(PAGSIZ - 1))
526/*
527 * move `len' bytes of data from process `pid'
528 * at address `addr' to our space at `laddr'
529 */
530int
531umoven(tcp, addr, len, laddr)
532struct tcb *tcp;
533long addr;
534int len;
535char *laddr;
536{
537
538#ifdef LINUX
539 int pid = tcp->pid;
540 int n, m;
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000541 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 union {
543 long val;
544 char x[sizeof(long)];
545 } u;
546
547 if (addr & (sizeof(long) - 1)) {
548 /* addr not a multiple of sizeof(long) */
549 n = addr - (addr & -sizeof(long)); /* residue */
550 addr &= -sizeof(long); /* residue */
551 errno = 0;
552 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
553 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000554 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000555 /* Ran into 'end of memory' - stupid "printpath" */
556 return 0;
557 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000558 /* But if not started, we had a bogus address. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000559 perror("ptrace: umoven");
560 return -1;
561 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000562 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000563 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
564 addr += sizeof(long), laddr += m, len -= m;
565 }
566 while (len) {
567 errno = 0;
568 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
569 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000570 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000571 /* Ran into 'end of memory' - stupid "printpath" */
572 return 0;
573 }
574 perror("ptrace: umoven");
575 return -1;
576 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000577 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000578 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
579 addr += sizeof(long), laddr += m, len -= m;
580 }
581#endif /* LINUX */
582
583#ifdef SUNOS4
584 int pid = tcp->pid;
585#if 0
586 int n, m;
587 union {
588 long val;
589 char x[sizeof(long)];
590 } u;
591
592 if (addr & (sizeof(long) - 1)) {
593 /* addr not a multiple of sizeof(long) */
594 n = addr - (addr & -sizeof(long)); /* residue */
595 addr &= -sizeof(long); /* residue */
596 errno = 0;
597 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
598 if (errno) {
599 perror("umoven");
600 return -1;
601 }
602 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
603 addr += sizeof(long), laddr += m, len -= m;
604 }
605 while (len) {
606 errno = 0;
607 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
608 if (errno) {
609 perror("umoven");
610 return -1;
611 }
612 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
613 addr += sizeof(long), laddr += m, len -= m;
614 }
615#else /* !oldway */
616 int n;
617
618 while (len) {
619 n = MIN(len, PAGSIZ);
620 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
621 if (ptrace(PTRACE_READDATA, pid,
622 (char *) addr, len, laddr) < 0) {
623 perror("umoven: ptrace(PTRACE_READDATA, ...)");
624 abort();
625 return -1;
626 }
627 len -= n;
628 addr += n;
629 laddr += n;
630 }
631#endif /* !oldway */
632#endif /* SUNOS4 */
633
634#ifdef SVR4
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000635#ifdef HAVE_MP_PROCFS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000636 if (pread(tcp->pfd_as, laddr, len, addr) == -1)
637 return -1;
638#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000639/*
640 * We would like to use pread preferentially for speed
641 * but even though SGI has it in their library, it no longer works.
642 */
643#ifdef MIPS
644#undef HAVE_PREAD
645#endif
646#ifdef HAVE_PREAD
647 if (pread(tcp->pfd, laddr, len, addr) == -1)
648 return -1;
649#else /* !HAVE_PREAD */
650 lseek(tcp->pfd, addr, SEEK_SET);
651 if (read(tcp->pfd, laddr, len) == -1)
652 return -1;
653#endif /* !HAVE_PREAD */
Wichert Akkermanea78f0f1999-11-29 15:34:02 +0000654#endif /* HAVE_MP_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655#endif /* SVR4 */
656
657 return 0;
658}
659
660/*
661 * like `umove' but make the additional effort of looking
662 * for a terminating zero byte.
663 */
664int
665umovestr(tcp, addr, len, laddr)
666struct tcb *tcp;
667long addr;
668int len;
669char *laddr;
670{
Wichert Akkerman71bdaff1999-05-28 10:28:56 +0000671#ifdef SVR4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000672 return umoven(tcp, addr, len, laddr);
673#else /* !SVR4 */
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000674 int started = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000675 int pid = tcp->pid;
676 int i, n, m;
677 union {
678 long val;
679 char x[sizeof(long)];
680 } u;
681
682 if (addr & (sizeof(long) - 1)) {
683 /* addr not a multiple of sizeof(long) */
684 n = addr - (addr & -sizeof(long)); /* residue */
685 addr &= -sizeof(long); /* residue */
686 errno = 0;
687 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
688 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000689 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000690 /* Ran into 'end of memory' - stupid "printpath" */
691 return 0;
692 }
693 perror("umovestr");
694 return -1;
695 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000696 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
698 while (n & (sizeof(long) - 1))
699 if (u.x[n++] == '\0')
700 return 0;
701 addr += sizeof(long), laddr += m, len -= m;
702 }
703 while (len) {
704 errno = 0;
705 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
706 if (errno) {
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000707 if (started && (errno==EPERM || errno==EIO)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000708 /* Ran into 'end of memory' - stupid "printpath" */
709 return 0;
710 }
711 perror("umovestr");
712 return -1;
713 }
Wichert Akkerman5daa0281999-03-15 19:49:42 +0000714 started = 1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
716 for (i = 0; i < sizeof(long); i++)
717 if (u.x[i] == '\0')
718 return 0;
719
720 addr += sizeof(long), laddr += m, len -= m;
721 }
722 return 0;
723#endif /* !SVR4 */
724}
725
726#ifdef LINUX
727#ifndef SPARC
728#define PTRACE_WRITETEXT 101
729#define PTRACE_WRITEDATA 102
730#endif /* !SPARC */
731#endif /* LINUX */
732
733#ifdef SUNOS4
734
735static int
736uload(cmd, pid, addr, len, laddr)
737int cmd;
738int pid;
739long addr;
740int len;
741char *laddr;
742{
743#if 0
744 int n;
745
746 while (len) {
747 n = MIN(len, PAGSIZ);
748 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
749 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
750 perror("uload: ptrace(PTRACE_WRITE, ...)");
751 return -1;
752 }
753 len -= n;
754 addr += n;
755 laddr += n;
756 }
757#else
758 int peek, poke;
759 int n, m;
760 union {
761 long val;
762 char x[sizeof(long)];
763 } u;
764
765 if (cmd == PTRACE_WRITETEXT) {
766 peek = PTRACE_PEEKTEXT;
767 poke = PTRACE_POKETEXT;
768 }
769 else {
770 peek = PTRACE_PEEKDATA;
771 poke = PTRACE_POKEDATA;
772 }
773 if (addr & (sizeof(long) - 1)) {
774 /* addr not a multiple of sizeof(long) */
775 n = addr - (addr & -sizeof(long)); /* residue */
776 addr &= -sizeof(long);
777 errno = 0;
778 u.val = ptrace(peek, pid, (char *) addr, 0);
779 if (errno) {
780 perror("uload: POKE");
781 return -1;
782 }
783 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
784 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
785 perror("uload: POKE");
786 return -1;
787 }
788 addr += sizeof(long), laddr += m, len -= m;
789 }
790 while (len) {
791 if (len < sizeof(long))
792 u.val = ptrace(peek, pid, (char *) addr, 0);
793 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
794 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
795 perror("uload: POKE");
796 return -1;
797 }
798 addr += sizeof(long), laddr += m, len -= m;
799 }
800#endif
801 return 0;
802}
803
804int
805tload(pid, addr, len, laddr)
806int pid;
807int addr, len;
808char *laddr;
809{
810 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
811}
812
813int
814dload(pid, addr, len, laddr)
815int pid;
816int addr;
817int len;
818char *laddr;
819{
820 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
821}
822
823#endif /* SUNOS4 */
824
825#ifndef SVR4
826
827int
828upeek(pid, off, res)
829int pid;
830long off;
831long *res;
832{
833 long val;
834
835#ifdef SUNOS4_KERNEL_ARCH_KLUDGE
836 {
837 static int is_sun4m = -1;
838 struct utsname name;
839
840 /* Round up the usual suspects. */
841 if (is_sun4m == -1) {
842 if (uname(&name) < 0) {
843 perror("upeek: uname?");
844 exit(1);
845 }
846 is_sun4m = strcmp(name.machine, "sun4m") == 0;
847 if (is_sun4m) {
848 extern struct xlat struct_user_offsets[];
849 struct xlat *x;
850
851 for (x = struct_user_offsets; x->str; x++)
852 x->val += 1024;
853 }
854 }
855 if (is_sun4m)
856 off += 1024;
857 }
858#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
859 errno = 0;
860 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0);
861 if (val == -1 && errno) {
862 perror("upeek: ptrace(PTRACE_PEEKUSER, ... )");
863 return -1;
864 }
865 *res = val;
866 return 0;
867}
868
869#endif /* !SVR4 */
870
871long
872getpc(tcp)
873struct tcb *tcp;
874{
875
876#ifdef LINUX
877 long pc;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000878#if defined(I386)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879 if (upeek(tcp->pid, 4*EIP, &pc) < 0)
880 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000881#elif defined(IA64)
882 if (upeek(tcp->pid, PT_B0, &pc) < 0)
883 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000884#elif defined(ARM)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000885 if (upeek(tcp->pid, 4*15, &pc) < 0)
886 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000887#elif defined(POWERPC)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000888 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)
889 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000890#elif defined(M68k)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000891 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
892 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000893#elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 if (upeek(tcp->pid, REG_PC, &pc) < 0)
895 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000896#elif defined(MIPS)
897 if (upeek(tcp->pid, REG_EPC, &pc) < 0)
898 return -1;
899#elif defined(SPARC)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000900 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
902 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000903 pc = regs.r_pc;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000904#elif defined(S390)
905 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
Wichert Akkerman7a0b6491999-12-23 15:08:17 +0000906#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000907 return pc;
908#endif /* LINUX */
909
910#ifdef SUNOS4
911 /*
912 * Return current program counter for `pid'
913 * Assumes PC is never 0xffffffff
914 */
915 struct regs regs;
916
917 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
918 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
919 return -1;
920 }
921 return regs.r_pc;
922#endif /* SUNOS4 */
923
924#ifdef SVR4
925 /* XXX */
926 return 0;
927#endif /* SVR4 */
928
929}
930
931void
932printcall(tcp)
933struct tcb *tcp;
934{
935
936#ifdef LINUX
937#ifdef I386
938 long eip;
939
940 if (upeek(tcp->pid, 4*EIP, &eip) < 0) {
941 tprintf("[????????] ");
942 return;
943 }
944 tprintf("[%08lx] ", eip);
945#else /* !I386K */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000946#ifdef IA64
947 long ip;
948
949 if (upeek(tcp->pid, PT_B0, &ip) < 0) {
950 tprintf("[????????] ");
951 return;
952 }
953 tprintf("[%08lx] ", ip);
954#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955#ifdef POWERPC
956 long pc;
957
958 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0) {
959 tprintf ("[????????] ");
960 return;
961 }
962 tprintf("[%08lx] ", pc);
963#else /* !POWERPC */
964#ifdef M68K
965 long pc;
966
967 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) {
968 tprintf ("[????????] ");
969 return;
970 }
971 tprintf("[%08lx] ", pc);
972#else /* !M68K */
973#ifdef ALPHA
974 long pc;
975
976 if (upeek(tcp->pid, REG_PC, &pc) < 0) {
977 tprintf ("[????????] ");
978 return;
979 }
980 tprintf("[%08lx] ", pc);
981#else /* !ALPHA */
982#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000983 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
985 tprintf("[????????] ");
986 return;
987 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +0000988 tprintf("[%08lx] ", regs.r_pc);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989#endif /* SPARC */
990#endif /* ALPHA */
991#endif /* !M68K */
992#endif /* !POWERPC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000993#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994#endif /* !I386 */
995#endif /* LINUX */
996
997#ifdef SUNOS4
998 struct regs regs;
999
1000 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1001 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1002 tprintf("[????????] ");
1003 return;
1004 }
1005 tprintf("[%08x] ", regs.r_o7);
1006#endif /* SUNOS4 */
1007
1008#ifdef SVR4
1009 /* XXX */
1010 tprintf("[????????] ");
1011#endif
1012
1013}
1014
1015#ifndef SVR4
1016
1017int
1018setbpt(tcp)
1019struct tcb *tcp;
1020{
1021
1022#ifdef LINUX
1023#ifdef SPARC
1024 /* We simply use the SunOS breakpoint code. */
1025
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001026 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001027#define LOOPA 0x30800000 /* ba,a 0 */
1028
1029 if (tcp->flags & TCB_BPTSET) {
1030 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1031 return -1;
1032 }
1033 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1034 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1035 return -1;
1036 }
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001037 tcp->baddr = regs.r_o7 + 8;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038 errno = 0;
1039 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1040 if(errno) {
1041 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1042 return -1;
1043 }
1044
1045 /*
1046 * XXX - BRUTAL MODE ON
1047 * We cannot set a real BPT in the child, since it will not be
1048 * traced at the moment it will reach the trap and would probably
1049 * die with a core dump.
1050 * Thus, we are force our way in by taking out two instructions
1051 * and insert an eternal loop instead, in expectance of the SIGSTOP
1052 * generated by out PTRACE_ATTACH.
1053 * Of cause, if we evaporate ourselves in the middle of all this...
1054 */
1055 errno = 0;
1056 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);
1057 if(errno) {
1058 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1059 return -1;
1060 }
1061 tcp->flags |= TCB_BPTSET;
1062
1063#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001064#ifdef IA64
1065 /*
1066 * Our strategy here is to replace the bundle that contained
1067 * the clone() syscall with a bundle of the form:
1068 *
1069 * { 1: br 1b; br 1b; br 1b }
1070 *
1071 * This ensures that the newly forked child will loop
1072 * endlessly until we've got a chance to attach to it.
1073 */
1074 {
1075# define LOOP0 0x0000100000000017
1076# define LOOP1 0x4000000000200000
1077 unsigned long addr, ipsr;
1078 pid_t pid;
1079
1080 pid = tcp->pid;
1081 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1082 return -1;
1083 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1084 return -1;
1085 tcp->baddr = addr | ((ipsr >> 41) & 0x3); /* store "ri" in low two bits */
1086
1087 errno = 0;
1088 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0, 0);
1089 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8, 0);
1090 if (errno) {
1091 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1092 return -1;
1093 }
1094
1095 errno = 0;
1096 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1097 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1098 if (errno) {
1099 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1100 return -1;
1101 }
1102 tcp->flags |= TCB_BPTSET;
1103 }
1104#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001105
1106#if defined (I386)
1107#define LOOP 0x0000feeb
1108#elif defined (M68K)
1109#define LOOP 0x60fe0000
1110#elif defined (ALPHA)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001111#define LOOP 0xc3ffffff
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112#elif defined (POWERPC)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001113#define LOOP 0x0000feeb
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001114#elif defined(ARM)
Wichert Akkerman9a8a37f1999-12-24 23:19:31 +00001115#define LOOP 0xEAFFFFFE
Wichert Akkermanf90da011999-10-31 21:15:38 +00001116#elif defined(MIPS)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001117#define LOOP 0x1000ffff
1118#elif defined(S390)
1119#define LOOP 0xa7f40000 /* BRC 15,0 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120#else
1121#error unknown architecture
1122#endif
1123
1124 if (tcp->flags & TCB_BPTSET) {
1125 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1126 return -1;
1127 }
1128#if defined (I386)
1129 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)
1130 return -1;
1131#elif defined (M68K)
1132 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)
1133 return -1;
1134#elif defined (ALPHA)
1135 return -1;
1136#elif defined (ARM)
1137 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001138#elif defined (MIPS)
1139 return -1; /* FIXME: I do not know what i do - Flo */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140#elif defined (POWERPC)
1141 if (upeek(tcp->pid, 4*PT_NIP, &tcp->baddr) < 0)
1142 return -1;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001143#elif defined(S390)
1144 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)
1145 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146#else
1147#error unknown architecture
1148#endif
1149 if (debug)
1150 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1151 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1152 if (errno) {
1153 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1154 return -1;
1155 }
1156 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1157 if (errno) {
1158 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1159 return -1;
1160 }
1161 tcp->flags |= TCB_BPTSET;
1162
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001163#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001164#endif /* SPARC */
1165#endif /* LINUX */
1166
1167#ifdef SUNOS4
1168#ifdef SPARC /* This code is slightly sparc specific */
1169
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001170 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171#define BPT 0x91d02001 /* ta 1 */
1172#define LOOP 0x10800000 /* ba 0 */
1173#define LOOPA 0x30800000 /* ba,a 0 */
1174#define NOP 0x01000000
1175#if LOOPA
1176 static int loopdeloop[1] = {LOOPA};
1177#else
1178 static int loopdeloop[2] = {LOOP, NOP};
1179#endif
1180
1181 if (tcp->flags & TCB_BPTSET) {
1182 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1183 return -1;
1184 }
1185 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1186 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1187 return -1;
1188 }
1189 tcp->baddr = regs.r_o7 + 8;
1190 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1191 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1192 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1193 return -1;
1194 }
1195
1196 /*
1197 * XXX - BRUTAL MODE ON
1198 * We cannot set a real BPT in the child, since it will not be
1199 * traced at the moment it will reach the trap and would probably
1200 * die with a core dump.
1201 * Thus, we are force our way in by taking out two instructions
1202 * and insert an eternal loop in stead, in expectance of the SIGSTOP
1203 * generated by out PTRACE_ATTACH.
1204 * Of cause, if we evaporate ourselves in the middle of all this...
1205 */
1206 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1207 sizeof loopdeloop, (char *) loopdeloop) < 0) {
1208 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1209 return -1;
1210 }
1211 tcp->flags |= TCB_BPTSET;
1212
1213#endif /* SPARC */
1214#endif /* SUNOS4 */
1215
1216 return 0;
1217}
1218
1219int
1220clearbpt(tcp)
1221struct tcb *tcp;
1222{
1223
1224#ifdef LINUX
1225#ifdef I386
1226 long eip;
1227#else /* !I386 */
1228#ifdef POWERPC
1229 long pc;
1230#else /* !POWERPC */
1231#ifdef M68K
1232 long pc;
1233#else /* !M68K */
1234#ifdef ALPHA
1235 long pc;
1236#endif /* ALPHA */
1237#endif /* !M68K */
1238#endif /* !POWERPC */
1239#endif /* !I386 */
1240
1241#ifdef SPARC
1242 /* Again, we borrow the SunOS breakpoint code. */
1243 if (!(tcp->flags & TCB_BPTSET)) {
1244 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1245 return -1;
1246 }
1247 errno = 0;
1248 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1249 if(errno) {
1250 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1251 return -1;
1252 }
1253 tcp->flags &= ~TCB_BPTSET;
1254#else /* !SPARC */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001255#ifdef IA64
1256 {
1257 unsigned long addr, ipsr;
1258 pid_t pid;
1259
1260 pid = tcp->pid;
1261
1262 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)
1263 return -1;
1264 if (upeek(pid, PT_CR_IIP, &addr) < 0)
1265 return -1;
1266
1267 /* restore original bundle: */
1268 errno = 0;
1269 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
1270 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
1271 if (errno) {
1272 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
1273 return -1;
1274 }
1275
1276 /* restore original "ri" in ipsr: */
1277 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
1278 errno = 0;
1279 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
1280 if (errno) {
1281 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
1282 return -1;
1283 }
1284
1285 tcp->flags &= ~TCB_BPTSET;
1286
1287 if (addr != (tcp->baddr & ~0x3)) {
1288 /* the breakpoint has not been reached yet. */
1289 if (debug)
1290 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1291 addr, tcp->baddr);
1292 return 0;
1293 }
1294 }
1295#else /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001296
1297 if (debug)
1298 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
1299 if (!(tcp->flags & TCB_BPTSET)) {
1300 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1301 return -1;
1302 }
1303 errno = 0;
1304 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
1305 if (errno) {
1306 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
1307 return -1;
1308 }
1309 tcp->flags &= ~TCB_BPTSET;
1310
1311#ifdef I386
1312 if (upeek(tcp->pid, 4*EIP, &eip) < 0)
1313 return -1;
1314 if (eip != tcp->baddr) {
1315 /* The breakpoint has not been reached yet. */
1316 if (debug)
1317 fprintf(stderr,
1318 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1319 eip, tcp->baddr);
1320 return 0;
1321 }
1322#else /* !I386 */
1323#ifdef POWERPC
1324 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)
1325 return -1;
1326 if (pc != tcp->baddr) {
1327 /* The breakpoint has not been reached yet. */
1328 if (debug)
1329 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1330 pc, tcp->baddr);
1331 return 0;
1332 }
1333#else /* !POWERPC */
1334#ifdef M68K
1335 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)
1336 return -1;
1337 if (pc != tcp->baddr) {
1338 /* The breakpoint has not been reached yet. */
1339 if (debug)
1340 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1341 pc, tcp->baddr);
1342 return 0;
1343 }
1344#else /* !M68K */
1345#ifdef ALPHA
1346 if (upeek(tcp->pid, REG_PC, &pc) < 0)
1347 return -1;
1348 if (pc != tcp->baddr) {
1349 /* The breakpoint has not been reached yet. */
1350 if (debug)
1351 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
1352 pc, tcp->baddr);
1353 return 0;
1354 }
1355#endif /* ALPHA */
1356#endif /* !M68K */
1357#endif /* !POWERPC */
1358#endif /* !I386 */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001359#endif /* !IA64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360#endif /* !SPARC */
1361#endif /* LINUX */
1362
1363#ifdef SUNOS4
1364#ifdef SPARC
1365
1366#if !LOOPA
Wichert Akkermane6f876c1999-06-22 15:28:30 +00001367 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001368#endif
1369
1370 if (!(tcp->flags & TCB_BPTSET)) {
1371 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1372 return -1;
1373 }
1374 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1375 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1376 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1377 return -1;
1378 }
1379 tcp->flags &= ~TCB_BPTSET;
1380
1381#if !LOOPA
1382 /*
1383 * Since we don't have a single instruction breakpoint, we may have
1384 * to adjust the program counter after removing the our `breakpoint'.
1385 */
1386 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1387 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1388 return -1;
1389 }
1390 if ((regs.r_pc < tcp->baddr) ||
1391 (regs.r_pc > tcp->baddr + 4)) {
1392 /* The breakpoint has not been reached yet */
1393 if (debug)
1394 fprintf(stderr,
1395 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1396 regs.r_pc, tcp->parent->baddr);
1397 return 0;
1398 }
1399 if (regs.r_pc != tcp->baddr)
1400 if (debug)
1401 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1402 regs.r_pc, tcp->baddr);
1403
1404 regs.r_pc = tcp->baddr;
1405 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1406 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1407 return -1;
1408 }
1409#endif /* LOOPA */
1410#endif /* SPARC */
1411#endif /* SUNOS4 */
1412
1413 return 0;
1414}
1415
1416#endif /* !SVR4 */
1417
1418#ifdef SUNOS4
1419
1420static int
1421getex(pid, hdr)
1422int pid;
1423struct exec *hdr;
1424{
1425 int n;
1426
1427 for (n = 0; n < sizeof *hdr; n += 4) {
1428 long res;
1429 if (upeek(pid, uoff(u_exdata) + n, &res) < 0)
1430 return -1;
1431 memcpy(((char *) hdr) + n, &res, 4);
1432 }
1433 if (debug) {
1434 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1435 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1436 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1437 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1438 }
1439 return 0;
1440}
1441
1442int
1443fixvfork(tcp)
1444struct tcb *tcp;
1445{
1446 int pid = tcp->pid;
1447 /*
1448 * Change `vfork' in a freshly exec'ed dynamically linked
1449 * executable's (internal) symbol table to plain old `fork'
1450 */
1451
1452 struct exec hdr;
1453 struct link_dynamic dyn;
1454 struct link_dynamic_2 ld;
1455 char *strtab, *cp;
1456
1457 if (getex(pid, &hdr) < 0)
1458 return -1;
1459 if (!hdr.a_dynamic)
1460 return -1;
1461
1462 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1463 fprintf(stderr, "Cannot read DYNAMIC\n");
1464 return -1;
1465 }
1466 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1467 fprintf(stderr, "Cannot read link_dynamic_2\n");
1468 return -1;
1469 }
1470 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
1471 fprintf(stderr, "fixvfork: out of memory\n");
1472 return -1;
1473 }
1474 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1475 (int)ld.ld_symb_size, strtab) < 0)
1476 goto err;
1477
1478#if 0
1479 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1480 fprintf(stderr, "[symbol: %s]\n", cp);
1481 cp += strlen(cp)+1;
1482 }
1483 return 0;
1484#endif
1485 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1486 if (strcmp(cp, "_vfork") == 0) {
1487 if (debug)
1488 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1489 strcpy(cp, "_fork");
1490 break;
1491 }
1492 cp += strlen(cp)+1;
1493 }
1494 if (cp < strtab + ld.ld_symb_size)
1495 /*
1496 * Write entire symbol table back to avoid
1497 * memory alignment bugs in ptrace
1498 */
1499 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1500 (int)ld.ld_symb_size, strtab) < 0)
1501 goto err;
1502
1503 free(strtab);
1504 return 0;
1505
1506err:
1507 free(strtab);
1508 return -1;
1509}
1510
1511#endif /* SUNOS4 */