]> granicus.if.org Git - strace/blob - util.c
Ignore errors if a thread is killed
[strace] / util.c
1 /*
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>
5  * 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>
9  * 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 <signal.h>
39 #include <sys/syscall.h>
40 #include <sys/user.h>
41 #include <sys/param.h>
42 #include <fcntl.h>
43 #if HAVE_SYS_UIO_H
44 #include <sys/uio.h>
45 #endif
46 #ifdef SUNOS4
47 #include <machine/reg.h>
48 #include <a.out.h>
49 #include <link.h>
50 #endif /* SUNOS4 */
51
52 #if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1))
53 #include <linux/ptrace.h>
54 #endif
55
56 #if defined(LINUX) && defined(IA64)
57 # include <asm/ptrace_offsets.h>
58 # include <asm/rse.h>
59 #endif
60
61 #ifdef HAVE_SYS_REG_H
62 #include <sys/reg.h>
63 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
65 #undef PTRACE_SYSCALL
66 # ifdef HAVE_STRUCT_IA64_FPREG
67 #  define ia64_fpreg XXX_ia64_fpreg
68 # endif
69 # ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70 #  define pt_all_user_regs XXX_pt_all_user_regs
71 # endif
72 #include <linux/ptrace.h>
73 # undef ia64_fpreg
74 # undef pt_all_user_regs
75 #endif
76
77 #ifdef SUNOS4_KERNEL_ARCH_KLUDGE
78 #include <sys/utsname.h>
79 #endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
80
81 #if defined(LINUXSPARC) && defined (SPARC64)
82 # undef PTRACE_GETREGS
83 # define PTRACE_GETREGS PTRACE_GETREGS64
84 # undef PTRACE_SETREGS
85 # define PTRACE_SETREGS PTRACE_SETREGS64
86 #endif
87
88 /* macros */
89 #ifndef MAX
90 #define MAX(a,b)                (((a) > (b)) ? (a) : (b))
91 #endif
92 #ifndef MIN
93 #define MIN(a,b)                (((a) < (b)) ? (a) : (b))
94 #endif
95
96 #if 0
97 void
98 tv_tv(tv, a, b)
99 struct timeval *tv;
100 int a;
101 int b;
102 {
103         tv->tv_sec = a;
104         tv->tv_usec = b;
105 }
106 #endif
107
108 int
109 tv_nz(a)
110 struct timeval *a;
111 {
112         return a->tv_sec || a->tv_usec;
113 }
114
115 int
116 tv_cmp(a, b)
117 struct timeval *a, *b;
118 {
119         if (a->tv_sec < b->tv_sec
120             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
121                 return -1;
122         if (a->tv_sec > b->tv_sec
123             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
124                 return 1;
125         return 0;
126 }
127
128 double
129 tv_float(tv)
130 struct timeval *tv;
131 {
132         return tv->tv_sec + tv->tv_usec/1000000.0;
133 }
134
135 void
136 tv_add(tv, a, b)
137 struct timeval *tv, *a, *b;
138 {
139         tv->tv_sec = a->tv_sec + b->tv_sec;
140         tv->tv_usec = a->tv_usec + b->tv_usec;
141         if (tv->tv_usec >= 1000000) {
142                 tv->tv_sec++;
143                 tv->tv_usec -= 1000000;
144         }
145 }
146
147 void
148 tv_sub(tv, a, b)
149 struct timeval *tv, *a, *b;
150 {
151         tv->tv_sec = a->tv_sec - b->tv_sec;
152         tv->tv_usec = a->tv_usec - b->tv_usec;
153         if (((long) tv->tv_usec) < 0) {
154                 tv->tv_sec--;
155                 tv->tv_usec += 1000000;
156         }
157 }
158
159 void
160 tv_div(tv, a, n)
161 struct timeval *tv, *a;
162 int n;
163 {
164         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
165         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
166         tv->tv_usec %= 1000000;
167 }
168
169 void
170 tv_mul(tv, a, n)
171 struct timeval *tv, *a;
172 int n;
173 {
174         tv->tv_usec = a->tv_usec * n;
175         tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
176         tv->tv_usec %= 1000000;
177 }
178
179 const char *
180 xlookup(const struct xlat *xlat, int val)
181 {
182         for (; xlat->str != NULL; xlat++)
183                 if (xlat->val == val)
184                         return xlat->str;
185         return NULL;
186 }
187
188 /*
189  * Generic ptrace wrapper which tracks ESRCH errors
190  * by setting tcp->ptrace_errno to ESRCH.
191  *
192  * We assume that ESRCH indicates likely process death (SIGKILL?),
193  * modulo bugs where process somehow ended up not stopped.
194  * Unfortunately kernel uses ESRCH for that case too. Oh well.
195  *
196  * Currently used by upeek() only.
197  * TODO: use this in all other ptrace() calls while decoding.
198  */
199 long
200 do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
201 {
202         long l;
203
204         errno = 0;
205         l = ptrace(request, tcp->pid, addr, (long) data);
206         /* Non-ESRCH errors might be our invalid reg/mem accesses,
207          * we do not record them. */
208         if (errno == ESRCH)
209                 tcp->ptrace_errno = ESRCH;
210         return l;
211 }
212
213 /*
214  * Used when we want to unblock stopped traced process.
215  * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
216  * Returns 0 on success or if error was ESRCH
217  * (presumably process was killed while we talk to it).
218  * Otherwise prints error message and returns -1.
219  */
220 int
221 ptrace_restart(int op, struct tcb *tcp, int sig)
222 {
223         int err;
224         const char *msg;
225
226         errno = 0;
227         ptrace(op, tcp->pid, (void *) 1, (long) sig);
228         err = errno;
229         if (!err || err == ESRCH)
230                 return 0;
231
232         tcp->ptrace_errno = err;
233         msg = "SYSCALL";
234         if (op == PTRACE_CONT)
235                 msg = "CONT";
236         if (op == PTRACE_DETACH)
237                 msg = "DETACH";
238         fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
239                         msg, sig, strerror(err));
240         return -1;
241 }
242
243 /*
244  * Print entry in struct xlat table, if there.
245  */
246 void
247 printxval(const struct xlat *xlat, int val, const char *dflt)
248 {
249         const char *str = xlookup(xlat, val);
250
251         if (str)
252                 tprintf("%s", str);
253         else
254                 tprintf("%#x /* %s */", val, dflt);
255 }
256
257 #if HAVE_LONG_LONG
258 /*
259  * Print 64bit argument at position llarg and return the index of the next
260  * argument.
261  */
262 int
263 printllval(struct tcb *tcp, const char *format, int llarg)
264 {
265 # if defined(FREEBSD) \
266      || (defined(LINUX) && defined(POWERPC) && !defined(__powerpc64__)) \
267      || defined (LINUX_MIPSO32)
268         /* Align 64bit argument to 64bit boundary.  */
269         if (llarg % 2) llarg++;
270 # endif
271 # if defined LINUX && defined X86_64
272         if (current_personality == 0) {
273                 tprintf(format, tcp->u_arg[llarg]);
274                 llarg++;
275         } else {
276                 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
277                 llarg += 2;
278         }
279 # elif defined IA64 || defined ALPHA || (defined POWERPC && defined __powerpc64__)
280         tprintf(format, tcp->u_arg[llarg]);
281         llarg++;
282 # elif defined LINUX_MIPSN32
283         tprintf(format, tcp->ext_arg[llarg]);
284         llarg++;
285 # else
286         tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
287         llarg += 2;
288 # endif
289         return llarg;
290 }
291 #endif
292
293 /*
294  * Interpret `xlat' as an array of flags
295  * print the entries whose bits are on in `flags'
296  * return # of flags printed.
297  */
298 int
299 addflags(xlat, flags)
300 const struct xlat *xlat;
301 int flags;
302 {
303         int n;
304
305         for (n = 0; xlat->str; xlat++) {
306                 if (xlat->val && (flags & xlat->val) == xlat->val) {
307                         tprintf("|%s", xlat->str);
308                         flags &= ~xlat->val;
309                         n++;
310                 }
311         }
312         if (flags) {
313                 tprintf("|%#x", flags);
314                 n++;
315         }
316         return n;
317 }
318
319 /*
320  * Interpret `xlat' as an array of flags/
321  * Print to static string the entries whose bits are on in `flags'
322  * Return static string.
323  */
324 const char *
325 sprintflags(const char *prefix, const struct xlat *xlat, int flags)
326 {
327         static char outstr[1024];
328         int found = 0;
329
330         strcpy(outstr, prefix);
331
332         for (; xlat->str; xlat++) {
333                 if ((flags & xlat->val) == xlat->val) {
334                         if (found)
335                                 strcat(outstr, "|");
336                         strcat(outstr, xlat->str);
337                         flags &= ~xlat->val;
338                         found = 1;
339                 }
340         }
341         if (flags) {
342                 if (found)
343                         strcat(outstr, "|");
344                 sprintf(outstr + strlen(outstr), "%#x", flags);
345         }
346
347         return outstr;
348 }
349
350 int
351 printflags(xlat, flags, dflt)
352 const struct xlat *xlat;
353 int flags;
354 const char *dflt;
355 {
356         int n;
357         char *sep;
358
359         if (flags == 0 && xlat->val == 0) {
360                 tprintf("%s", xlat->str);
361                 return 1;
362         }
363
364         sep = "";
365         for (n = 0; xlat->str; xlat++) {
366                 if (xlat->val && (flags & xlat->val) == xlat->val) {
367                         tprintf("%s%s", sep, xlat->str);
368                         flags &= ~xlat->val;
369                         sep = "|";
370                         n++;
371                 }
372         }
373
374         if (n) {
375                 if (flags) {
376                         tprintf("%s%#x", sep, flags);
377                         n++;
378                 }
379         } else {
380                 if (flags) {
381                         tprintf("%#x", flags);
382                         if (dflt)
383                                 tprintf(" /* %s */", dflt);
384                 } else {
385                         if (dflt)
386                                 tprintf("0");
387                 }
388         }
389
390         return n;
391 }
392
393 void
394 printnum(tcp, addr, fmt)
395 struct tcb *tcp;
396 long addr;
397 char *fmt;
398 {
399         long num;
400
401         if (!addr) {
402                 tprintf("NULL");
403                 return;
404         }
405         if (umove(tcp, addr, &num) < 0) {
406                 tprintf("%#lx", addr);
407                 return;
408         }
409         tprintf("[");
410         tprintf(fmt, num);
411         tprintf("]");
412 }
413
414 void
415 printnum_int(tcp, addr, fmt)
416 struct tcb *tcp;
417 long addr;
418 char *fmt;
419 {
420         int num;
421
422         if (!addr) {
423                 tprintf("NULL");
424                 return;
425         }
426         if (umove(tcp, addr, &num) < 0) {
427                 tprintf("%#lx", addr);
428                 return;
429         }
430         tprintf("[");
431         tprintf(fmt, num);
432         tprintf("]");
433 }
434
435 void
436 printuid(text, uid)
437 const char *text;
438 unsigned long uid;
439 {
440         tprintf("%s", text);
441         tprintf((uid == -1) ? "%ld" : "%lu", uid);
442 }
443
444 static char path[MAXPATHLEN + 1];
445
446 /*
447  * Quote string `instr' of length `size'
448  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
449  * If `len' < 0, treat `instr' as a NUL-terminated string
450  * and quote at most (`size' - 1) bytes.
451  */
452 static int
453 string_quote(const char *instr, char *outstr, int len, int size)
454 {
455         const unsigned char *ustr = (const unsigned char *) instr;
456         char *s = outstr;
457         int usehex = 0, c, i;
458
459         if (xflag > 1)
460                 usehex = 1;
461         else if (xflag) {
462                 /* Check for presence of symbol which require
463                    to hex-quote the whole string. */
464                 for (i = 0; i < size; ++i) {
465                         c = ustr[i];
466                         /* Check for NUL-terminated string. */
467                         if (len < 0) {
468                                 if (c == '\0')
469                                         break;
470                                 /* Quote at most size - 1 bytes. */
471                                 if (i == size - 1)
472                                         continue;
473                         }
474                         if (!isprint(c) && !isspace(c)) {
475                                 usehex = 1;
476                                 break;
477                         }
478                 }
479         }
480
481         *s++ = '\"';
482
483         if (usehex) {
484                 /* Hex-quote the whole string. */
485                 for (i = 0; i < size; ++i) {
486                         c = ustr[i];
487                         /* Check for NUL-terminated string. */
488                         if (len < 0) {
489                                 if (c == '\0')
490                                         break;
491                                 /* Quote at most size - 1 bytes. */
492                                 if (i == size - 1)
493                                         continue;
494                         }
495                         sprintf(s, "\\x%02x", c);
496                         s += 4;
497                 }
498         } else {
499                 for (i = 0; i < size; ++i) {
500                         c = ustr[i];
501                         /* Check for NUL-terminated string. */
502                         if (len < 0) {
503                                 if (c == '\0')
504                                         break;
505                                 /* Quote at most size - 1 bytes. */
506                                 if (i == size - 1)
507                                         continue;
508                         }
509                         switch (c) {
510                                 case '\"': case '\\':
511                                         *s++ = '\\';
512                                         *s++ = c;
513                                         break;
514                                 case '\f':
515                                         *s++ = '\\';
516                                         *s++ = 'f';
517                                         break;
518                                 case '\n':
519                                         *s++ = '\\';
520                                         *s++ = 'n';
521                                         break;
522                                 case '\r':
523                                         *s++ = '\\';
524                                         *s++ = 'r';
525                                         break;
526                                 case '\t':
527                                         *s++ = '\\';
528                                         *s++ = 't';
529                                         break;
530                                 case '\v':
531                                         *s++ = '\\';
532                                         *s++ = 'v';
533                                         break;
534                                 default:
535                                         if (isprint(c))
536                                                 *s++ = c;
537                                         else if (i + 1 < size
538                                                  && isdigit(ustr[i + 1])) {
539                                                 sprintf(s, "\\%03o", c);
540                                                 s += 4;
541                                         } else {
542                                                 sprintf(s, "\\%o", c);
543                                                 s += strlen(s);
544                                         }
545                                         break;
546                         }
547                 }
548         }
549
550         *s++ = '\"';
551         *s = '\0';
552
553         /* Return nonzero if the string was unterminated.  */
554         return i == size;
555 }
556
557 /*
558  * Print path string specified by address `addr' and length `n'.
559  * If path length exceeds `n', append `...' to the output.
560  */
561 void
562 printpathn(struct tcb *tcp, long addr, int n)
563 {
564         if (!addr) {
565                 tprintf("NULL");
566                 return;
567         }
568
569         /* Cap path length to the path buffer size,
570            and NUL-terminate the buffer. */
571         if (n > sizeof path - 1)
572                 n = sizeof path - 1;
573         path[n] = '\0';
574
575         /* Fetch one byte more to find out whether path length > n. */
576         if (umovestr(tcp, addr, n + 1, path) < 0)
577                 tprintf("%#lx", addr);
578         else {
579                 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
580                 int trunc = (path[n] != '\0');
581
582                 if (trunc)
583                         path[n] = '\0';
584                 (void) string_quote(path, outstr, -1, n + 1);
585                 if (trunc)
586                         strcat(outstr, "...");
587                 tprintf("%s", outstr);
588         }
589 }
590
591 void
592 printpath(struct tcb *tcp, long addr)
593 {
594         printpathn(tcp, addr, sizeof path - 1);
595 }
596
597 /*
598  * Print string specified by address `addr' and length `len'.
599  * If `len' < 0, treat the string as a NUL-terminated string.
600  * If string length exceeds `max_strlen', append `...' to the output.
601  */
602 void
603 printstr(struct tcb *tcp, long addr, int len)
604 {
605         static char *str = NULL;
606         static char *outstr;
607         int size;
608
609         if (!addr) {
610                 tprintf("NULL");
611                 return;
612         }
613         /* Allocate static buffers if they are not allocated yet. */
614         if (!str)
615                 str = malloc(max_strlen + 1);
616         if (!outstr)
617                 outstr = malloc(4 * max_strlen + sizeof "\"...\"");
618         if (!str || !outstr) {
619                 fprintf(stderr, "out of memory\n");
620                 tprintf("%#lx", addr);
621                 return;
622         }
623
624         if (len < 0) {
625                 /*
626                  * Treat as a NUL-terminated string: fetch one byte more
627                  * because string_quote() quotes one byte less.
628                  */
629                 size = max_strlen + 1;
630                 str[max_strlen] = '\0';
631                 if (umovestr(tcp, addr, size, str) < 0) {
632                         tprintf("%#lx", addr);
633                         return;
634                 }
635         }
636         else {
637                 size = MIN(len, max_strlen);
638                 if (umoven(tcp, addr, size, str) < 0) {
639                         tprintf("%#lx", addr);
640                         return;
641                 }
642         }
643
644         if (string_quote(str, outstr, len, size) &&
645             (len < 0 || len > max_strlen))
646                 strcat(outstr, "...");
647
648         tprintf("%s", outstr);
649 }
650
651 #if HAVE_SYS_UIO_H
652 void
653 dumpiov(tcp, len, addr)
654 struct tcb * tcp;
655 int len;
656 long addr;
657 {
658 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
659         union {
660                 struct { u_int32_t base; u_int32_t len; } *iov32;
661                 struct { u_int64_t base; u_int64_t len; } *iov64;
662         } iovu;
663 #define iov iovu.iov64
664 #define sizeof_iov \
665   (personality_wordsize[current_personality] == 4 \
666    ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
667 #define iov_iov_base(i) \
668   (personality_wordsize[current_personality] == 4 \
669    ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
670 #define iov_iov_len(i) \
671   (personality_wordsize[current_personality] == 4 \
672    ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
673 #else
674         struct iovec *iov;
675 #define sizeof_iov sizeof(*iov)
676 #define iov_iov_base(i) iov[i].iov_base
677 #define iov_iov_len(i) iov[i].iov_len
678 #endif
679         int i;
680         unsigned long size;
681
682         size = sizeof_iov * (unsigned long) len;
683         if (size / sizeof_iov != len
684             || (iov = malloc(size)) == NULL) {
685                 fprintf(stderr, "out of memory\n");
686                 return;
687         }
688         if (umoven(tcp, addr, size, (char *) iov) >= 0) {
689                 for (i = 0; i < len; i++) {
690                         /* include the buffer number to make it easy to
691                          * match up the trace with the source */
692                         tprintf(" * %lu bytes in buffer %d\n",
693                                 (unsigned long)iov_iov_len(i), i);
694                         dumpstr(tcp, (long) iov_iov_base(i),
695                                 iov_iov_len(i));
696                 }
697         }
698         free((char *) iov);
699 #undef sizeof_iov
700 #undef iov_iov_base
701 #undef iov_iov_len
702 #undef iov
703 }
704 #endif
705
706 void
707 dumpstr(tcp, addr, len)
708 struct tcb *tcp;
709 long addr;
710 int len;
711 {
712         static int strsize = -1;
713         static unsigned char *str;
714         static char outstr[80];
715         char *s;
716         int i, j;
717
718         if (strsize < len) {
719                 if (str)
720                         free(str);
721                 if ((str = malloc(len)) == NULL) {
722                         fprintf(stderr, "out of memory\n");
723                         return;
724                 }
725                 strsize = len;
726         }
727
728         if (umoven(tcp, addr, len, (char *) str) < 0)
729                 return;
730
731         for (i = 0; i < len; i += 16) {
732                 s = outstr;
733                 sprintf(s, " | %05x ", i);
734                 s += 9;
735                 for (j = 0; j < 16; j++) {
736                         if (j == 8)
737                                 *s++ = ' ';
738                         if (i + j < len) {
739                                 sprintf(s, " %02x", str[i + j]);
740                                 s += 3;
741                         }
742                         else {
743                                 *s++ = ' '; *s++ = ' '; *s++ = ' ';
744                         }
745                 }
746                 *s++ = ' '; *s++ = ' ';
747                 for (j = 0; j < 16; j++) {
748                         if (j == 8)
749                                 *s++ = ' ';
750                         if (i + j < len) {
751                                 if (isprint(str[i + j]))
752                                         *s++ = str[i + j];
753                                 else
754                                         *s++ = '.';
755                         }
756                         else
757                                 *s++ = ' ';
758                 }
759                 tprintf("%s |\n", outstr);
760         }
761 }
762
763 #define PAGMASK (~(PAGSIZ - 1))
764 /*
765  * move `len' bytes of data from process `pid'
766  * at address `addr' to our space at `laddr'
767  */
768 int
769 umoven(struct tcb *tcp, long addr, int len, char *laddr)
770 {
771 #ifdef LINUX
772         int pid = tcp->pid;
773         int n, m;
774         int started = 0;
775         union {
776                 long val;
777                 char x[sizeof(long)];
778         } u;
779
780         if (addr & (sizeof(long) - 1)) {
781                 /* addr not a multiple of sizeof(long) */
782                 n = addr - (addr & -sizeof(long)); /* residue */
783                 addr &= -sizeof(long); /* residue */
784                 errno = 0;
785                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
786                 if (errno) {
787                         if (started && (errno==EPERM || errno==EIO)) {
788                                 /* Ran into 'end of memory' - stupid "printpath" */
789                                 return 0;
790                         }
791                         /* But if not started, we had a bogus address. */
792                         if (addr != 0 && errno != EIO && errno != ESRCH)
793                                 perror("ptrace: umoven");
794                         return -1;
795                 }
796                 started = 1;
797                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
798                 addr += sizeof(long), laddr += m, len -= m;
799         }
800         while (len) {
801                 errno = 0;
802                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
803                 if (errno) {
804                         if (started && (errno==EPERM || errno==EIO)) {
805                                 /* Ran into 'end of memory' - stupid "printpath" */
806                                 return 0;
807                         }
808                         if (addr != 0 && errno != EIO && errno != ESRCH)
809                                 perror("ptrace: umoven");
810                         return -1;
811                 }
812                 started = 1;
813                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
814                 addr += sizeof(long), laddr += m, len -= m;
815         }
816 #endif /* LINUX */
817
818 #ifdef SUNOS4
819         int pid = tcp->pid;
820 #if 0
821         int n, m;
822         union {
823                 long val;
824                 char x[sizeof(long)];
825         } u;
826
827         if (addr & (sizeof(long) - 1)) {
828                 /* addr not a multiple of sizeof(long) */
829                 n = addr - (addr & -sizeof(long)); /* residue */
830                 addr &= -sizeof(long); /* residue */
831                 errno = 0;
832                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
833                 if (errno) {
834                         if (errno != ESRCH)
835                                 perror("umoven");
836                         return -1;
837                 }
838                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
839                 addr += sizeof(long), laddr += m, len -= m;
840         }
841         while (len) {
842                 errno = 0;
843                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
844                 if (errno) {
845                         if (errno != ESRCH)
846                                 perror("umoven");
847                         return -1;
848                 }
849                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
850                 addr += sizeof(long), laddr += m, len -= m;
851         }
852 #else /* !oldway */
853         int n;
854
855         while (len) {
856                 n = MIN(len, PAGSIZ);
857                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
858                 if (ptrace(PTRACE_READDATA, pid,
859                            (char *) addr, len, laddr) < 0) {
860                         if (errno != ESRCH) {
861                                 perror("umoven: ptrace(PTRACE_READDATA, ...)");
862                                 abort();
863                         }
864                         return -1;
865                 }
866                 len -= n;
867                 addr += n;
868                 laddr += n;
869         }
870 #endif /* !oldway */
871 #endif /* SUNOS4 */
872
873 #ifdef USE_PROCFS
874 #ifdef HAVE_MP_PROCFS
875         int fd = tcp->pfd_as;
876 #else
877         int fd = tcp->pfd;
878 #endif
879         lseek(fd, addr, SEEK_SET);
880         if (read(fd, laddr, len) == -1)
881                 return -1;
882 #endif /* USE_PROCFS */
883
884         return 0;
885 }
886
887 /*
888  * like `umove' but make the additional effort of looking
889  * for a terminating zero byte.
890  */
891 int
892 umovestr(struct tcb *tcp, long addr, int len, char *laddr)
893 {
894 #ifdef USE_PROCFS
895 #ifdef HAVE_MP_PROCFS
896         int fd = tcp->pfd_as;
897 #else
898         int fd = tcp->pfd;
899 #endif
900         /* Some systems (e.g. FreeBSD) can be upset if we read off the
901            end of valid memory,  avoid this by trying to read up
902            to page boundaries.  But we don't know what a page is (and
903            getpagesize(2) (if it exists) doesn't necessarily return
904            hardware page size).  Assume all pages >= 1024 (a-historical
905            I know) */
906
907         int page = 1024;        /* How to find this? */
908         int move = page - (addr & (page - 1));
909         int left = len;
910
911         lseek(fd, addr, SEEK_SET);
912
913         while (left) {
914                 if (move > left) move = left;
915                 if ((move = read(fd, laddr, move)) <= 0)
916                         return left != len ? 0 : -1;
917                 if (memchr (laddr, 0, move)) break;
918                 left -= move;
919                 laddr += move;
920                 addr += move;
921                 move = page;
922         }
923 #else /* !USE_PROCFS */
924         int started = 0;
925         int pid = tcp->pid;
926         int i, n, m;
927         union {
928                 long val;
929                 char x[sizeof(long)];
930         } u;
931
932         if (addr & (sizeof(long) - 1)) {
933                 /* addr not a multiple of sizeof(long) */
934                 n = addr - (addr & -sizeof(long)); /* residue */
935                 addr &= -sizeof(long); /* residue */
936                 errno = 0;
937                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
938                 if (errno) {
939                         if (started && (errno==EPERM || errno==EIO)) {
940                                 /* Ran into 'end of memory' - stupid "printpath" */
941                                 return 0;
942                         }
943                         if (addr != 0 && errno != EIO && errno != ESRCH)
944                                 perror("umovestr");
945                         return -1;
946                 }
947                 started = 1;
948                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len));
949                 while (n & (sizeof(long) - 1))
950                         if (u.x[n++] == '\0')
951                                 return 0;
952                 addr += sizeof(long), laddr += m, len -= m;
953         }
954         while (len) {
955                 errno = 0;
956                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
957                 if (errno) {
958                         if (started && (errno==EPERM || errno==EIO)) {
959                                 /* Ran into 'end of memory' - stupid "printpath" */
960                                 return 0;
961                         }
962                         if (addr != 0 && errno != EIO && errno != ESRCH)
963                                 perror("umovestr");
964                         return -1;
965                 }
966                 started = 1;
967                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
968                 for (i = 0; i < sizeof(long); i++)
969                         if (u.x[i] == '\0')
970                                 return 0;
971
972                 addr += sizeof(long), laddr += m, len -= m;
973         }
974 #endif /* !USE_PROCFS */
975         return 0;
976 }
977
978 #ifdef LINUX
979 # if !defined (SPARC) && !defined(SPARC64)
980 #  define PTRACE_WRITETEXT      101
981 #  define PTRACE_WRITEDATA      102
982 # endif /* !SPARC && !SPARC64 */
983 #endif /* LINUX */
984
985 #ifdef SUNOS4
986
987 static int
988 uload(cmd, pid, addr, len, laddr)
989 int cmd;
990 int pid;
991 long addr;
992 int len;
993 char *laddr;
994 {
995 # if 0
996         int n;
997
998         while (len) {
999                 n = MIN(len, PAGSIZ);
1000                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
1001                 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) {
1002                         perror("uload: ptrace(PTRACE_WRITE, ...)");
1003                         return -1;
1004                 }
1005                 len -= n;
1006                 addr += n;
1007                 laddr += n;
1008         }
1009 # else
1010         int peek, poke;
1011         int n, m;
1012         union {
1013                 long val;
1014                 char x[sizeof(long)];
1015         } u;
1016
1017         if (cmd == PTRACE_WRITETEXT) {
1018                 peek = PTRACE_PEEKTEXT;
1019                 poke = PTRACE_POKETEXT;
1020         }
1021         else {
1022                 peek = PTRACE_PEEKDATA;
1023                 poke = PTRACE_POKEDATA;
1024         }
1025         if (addr & (sizeof(long) - 1)) {
1026                 /* addr not a multiple of sizeof(long) */
1027                 n = addr - (addr & -sizeof(long)); /* residue */
1028                 addr &= -sizeof(long);
1029                 errno = 0;
1030                 u.val = ptrace(peek, pid, (char *) addr, 0);
1031                 if (errno) {
1032                         perror("uload: POKE");
1033                         return -1;
1034                 }
1035                 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
1036                 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
1037                         perror("uload: POKE");
1038                         return -1;
1039                 }
1040                 addr += sizeof(long), laddr += m, len -= m;
1041         }
1042         while (len) {
1043                 if (len < sizeof(long))
1044                         u.val = ptrace(peek, pid, (char *) addr, 0);
1045                 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
1046                 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
1047                         perror("uload: POKE");
1048                         return -1;
1049                 }
1050                 addr += sizeof(long), laddr += m, len -= m;
1051         }
1052 # endif
1053         return 0;
1054 }
1055
1056 int
1057 tload(pid, addr, len, laddr)
1058 int pid;
1059 int addr, len;
1060 char *laddr;
1061 {
1062         return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
1063 }
1064
1065 int
1066 dload(pid, addr, len, laddr)
1067 int pid;
1068 int addr;
1069 int len;
1070 char *laddr;
1071 {
1072         return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
1073 }
1074
1075 #endif /* SUNOS4 */
1076
1077 #ifndef USE_PROCFS
1078
1079 int
1080 upeek(tcp, off, res)
1081 struct tcb *tcp;
1082 long off;
1083 long *res;
1084 {
1085         long val;
1086
1087 # ifdef SUNOS4_KERNEL_ARCH_KLUDGE
1088         {
1089                 static int is_sun4m = -1;
1090                 struct utsname name;
1091
1092                 /* Round up the usual suspects. */
1093                 if (is_sun4m == -1) {
1094                         if (uname(&name) < 0) {
1095                                 perror("upeek: uname?");
1096                                 exit(1);
1097                         }
1098                         is_sun4m = strcmp(name.machine, "sun4m") == 0;
1099                         if (is_sun4m) {
1100                                 const struct xlat *x;
1101
1102                                 for (x = struct_user_offsets; x->str; x++)
1103                                         x->val += 1024;
1104                         }
1105                 }
1106                 if (is_sun4m)
1107                         off += 1024;
1108         }
1109 # endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1110         errno = 0;
1111         val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
1112         if (val == -1 && errno) {
1113                 if (errno != ESRCH) {
1114                         char buf[60];
1115                         sprintf(buf,"upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1116                         perror(buf);
1117                 }
1118                 return -1;
1119         }
1120         *res = val;
1121         return 0;
1122 }
1123
1124 #endif /* !USE_PROCFS */
1125
1126 #if 0
1127 long
1128 getpc(struct tcb *tcp)
1129 {
1130
1131 #ifdef LINUX
1132         long pc;
1133 # if defined(I386)
1134         if (upeek(tcp, 4*EIP, &pc) < 0)
1135                 return -1;
1136 # elif defined(X86_64)
1137         if (upeek(tcp, 8*RIP, &pc) < 0)
1138                 return -1;
1139 # elif defined(IA64)
1140         if (upeek(tcp, PT_B0, &pc) < 0)
1141                 return -1;
1142 # elif defined(ARM)
1143         if (upeek(tcp, 4*15, &pc) < 0)
1144                 return -1;
1145 # elif defined(AVR32)
1146         if (upeek(tcp, REG_PC, &pc) < 0)
1147                 return -1;
1148 # elif defined(BFIN)
1149         if (upeek(tcp, REG_PC, &pc) < 0)
1150                 return -1;
1151 # elif defined(POWERPC)
1152         if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
1153                 return -1;
1154 # elif defined(M68K)
1155         if (upeek(tcp, 4*PT_PC, &pc) < 0)
1156                 return -1;
1157 # elif defined(ALPHA)
1158         if (upeek(tcp, REG_PC, &pc) < 0)
1159                 return -1;
1160 # elif defined(MIPS)
1161         if (upeek(tcp, REG_EPC, &pc) < 0)
1162                 return -1;
1163 # elif defined(SPARC) || defined(SPARC64)
1164         struct pt_regs regs;
1165         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1166                 return -1;
1167 #  if defined(SPARC64)
1168         pc = regs.tpc;
1169 #  else
1170         pc = regs.pc;
1171 #  endif
1172 # elif defined(S390) || defined(S390X)
1173         if(upeek(tcp,PT_PSWADDR,&pc) < 0)
1174                 return -1;
1175 # elif defined(HPPA)
1176         if(upeek(tcp,PT_IAOQ0,&pc) < 0)
1177                 return -1;
1178 # elif defined(SH)
1179         if (upeek(tcp, 4*REG_PC ,&pc) < 0)
1180                 return -1;
1181 # elif defined(SH64)
1182         if (upeek(tcp, REG_PC ,&pc) < 0)
1183                 return -1;
1184 # endif
1185         return pc;
1186 #endif /* LINUX */
1187
1188 #ifdef SUNOS4
1189         /*
1190          * Return current program counter for `pid'
1191          * Assumes PC is never 0xffffffff
1192          */
1193         struct regs regs;
1194
1195         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1196                 perror("getpc: ptrace(PTRACE_GETREGS, ...)");
1197                 return -1;
1198         }
1199         return regs.r_pc;
1200 #endif /* SUNOS4 */
1201
1202 #ifdef SVR4
1203         /* XXX */
1204         return 0;
1205 #endif /* SVR4 */
1206
1207 #ifdef FREEBSD
1208         struct reg regs;
1209         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1210         return regs.r_eip;
1211 #endif /* FREEBSD */
1212 }
1213 #endif /* 0 */
1214
1215 void
1216 printcall(struct tcb *tcp)
1217 {
1218 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1219                            sizeof(long) == 8 ? "[????????????????] " : \
1220                            NULL /* crash */)
1221
1222 #ifdef LINUX
1223 # ifdef I386
1224         long eip;
1225
1226         if (upeek(tcp, 4*EIP, &eip) < 0) {
1227                 PRINTBADPC;
1228                 return;
1229         }
1230         tprintf("[%08lx] ", eip);
1231
1232 # elif defined(S390) || defined(S390X)
1233         long psw;
1234         if(upeek(tcp,PT_PSWADDR,&psw) < 0) {
1235                 PRINTBADPC;
1236                 return;
1237         }
1238 #  ifdef S390
1239         tprintf("[%08lx] ", psw);
1240 #  elif S390X
1241         tprintf("[%16lx] ", psw);
1242 #  endif
1243
1244 # elif defined(X86_64)
1245         long rip;
1246
1247         if (upeek(tcp, 8*RIP, &rip) < 0) {
1248                 PRINTBADPC;
1249                 return;
1250         }
1251         tprintf("[%16lx] ", rip);
1252 # elif defined(IA64)
1253         long ip;
1254
1255         if (upeek(tcp, PT_B0, &ip) < 0) {
1256                 PRINTBADPC;
1257                 return;
1258         }
1259         tprintf("[%08lx] ", ip);
1260 # elif defined(POWERPC)
1261         long pc;
1262
1263         if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1264                 tprintf ("[????????] ");
1265                 return;
1266         }
1267         tprintf("[%08lx] ", pc);
1268 # elif defined(M68K)
1269         long pc;
1270
1271         if (upeek(tcp, 4*PT_PC, &pc) < 0) {
1272                 tprintf ("[????????] ");
1273                 return;
1274         }
1275         tprintf("[%08lx] ", pc);
1276 # elif defined(ALPHA)
1277         long pc;
1278
1279         if (upeek(tcp, REG_PC, &pc) < 0) {
1280                 tprintf ("[????????????????] ");
1281                 return;
1282         }
1283         tprintf("[%08lx] ", pc);
1284 # elif defined(SPARC) || defined(SPARC64)
1285         struct pt_regs regs;
1286         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
1287                 PRINTBADPC;
1288                 return;
1289         }
1290 #  if defined(SPARC64)
1291         tprintf("[%08lx] ", regs.tpc);
1292 #  else
1293         tprintf("[%08lx] ", regs.pc);
1294 #  endif
1295 # elif defined(HPPA)
1296         long pc;
1297
1298         if(upeek(tcp,PT_IAOQ0,&pc) < 0) {
1299                 tprintf ("[????????] ");
1300                 return;
1301         }
1302         tprintf("[%08lx] ", pc);
1303 # elif defined(MIPS)
1304         long pc;
1305
1306         if (upeek(tcp, REG_EPC, &pc) < 0) {
1307                 tprintf ("[????????] ");
1308                 return;
1309         }
1310         tprintf("[%08lx] ", pc);
1311 # elif defined(SH)
1312         long pc;
1313
1314         if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1315                 tprintf ("[????????] ");
1316                 return;
1317         }
1318         tprintf("[%08lx] ", pc);
1319 # elif defined(SH64)
1320         long pc;
1321
1322         if (upeek(tcp, REG_PC, &pc) < 0) {
1323                 tprintf ("[????????????????] ");
1324                 return;
1325         }
1326         tprintf("[%08lx] ", pc);
1327 # elif defined(ARM)
1328         long pc;
1329
1330         if (upeek(tcp, 4*15, &pc) < 0) {
1331                 PRINTBADPC;
1332                 return;
1333         }
1334         tprintf("[%08lx] ", pc);
1335 # elif defined(AVR32)
1336         long pc;
1337
1338         if (upeek(tcp, REG_PC, &pc) < 0) {
1339                 tprintf("[????????] ");
1340                 return;
1341         }
1342         tprintf("[%08lx] ", pc);
1343 # elif defined(BFIN)
1344         long pc;
1345
1346         if (upeek(tcp, PT_PC, &pc) < 0) {
1347                 PRINTBADPC;
1348                 return;
1349         }
1350         tprintf("[%08lx] ", pc);
1351 #elif defined(CRISV10)
1352         long pc;
1353
1354         if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
1355                 PRINTBADPC;
1356                 return;
1357         }
1358         tprintf("[%08lx] ", pc);
1359 #elif defined(CRISV32)
1360         long pc;
1361
1362         if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
1363                 PRINTBADPC;
1364                 return;
1365         }
1366         tprintf("[%08lx] ", pc);
1367 # endif /* architecture */
1368 #endif /* LINUX */
1369
1370 #ifdef SUNOS4
1371         struct regs regs;
1372
1373         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1374                 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1375                 PRINTBADPC;
1376                 return;
1377         }
1378         tprintf("[%08x] ", regs.r_o7);
1379 #endif /* SUNOS4 */
1380
1381 #ifdef SVR4
1382         /* XXX */
1383         PRINTBADPC;
1384 #endif
1385
1386 #ifdef FREEBSD
1387         struct reg regs;
1388         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1389         tprintf("[%08x] ", regs.r_eip);
1390 #endif /* FREEBSD */
1391 }
1392
1393
1394 /*
1395  * These #if's are huge, please indent them correctly.
1396  * It's easy to get confused otherwise.
1397  */
1398 #ifndef USE_PROCFS
1399
1400 # if defined LINUX
1401
1402 #  include "syscall.h"
1403
1404 #  include <sys/syscall.h>
1405 #  ifndef CLONE_PTRACE
1406 #   define CLONE_PTRACE    0x00002000
1407 #  endif
1408 #  ifndef CLONE_VFORK
1409 #   define CLONE_VFORK     0x00004000
1410 #  endif
1411 #  ifndef CLONE_VM
1412 #   define CLONE_VM        0x00000100
1413 #  endif
1414 #  ifndef CLONE_STOPPED
1415 #   define CLONE_STOPPED   0x02000000
1416 #  endif
1417
1418 #  ifdef IA64
1419
1420 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1421    subsystem has them for x86... */
1422 #   define SYS_fork     2
1423 #   define SYS_vfork    190
1424
1425 typedef unsigned long *arg_setup_state;
1426
1427 static int
1428 arg_setup(struct tcb *tcp, arg_setup_state *state)
1429 {
1430         unsigned long cfm, sof, sol;
1431         long bsp;
1432
1433         if (ia32) {
1434                 /* Satisfy a false GCC warning.  */
1435                 *state = NULL;
1436                 return 0;
1437         }
1438
1439         if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1440                 return -1;
1441         if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1442                 return -1;
1443
1444         sof = (cfm >> 0) & 0x7f;
1445         sol = (cfm >> 7) & 0x7f;
1446         bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1447
1448         *state = (unsigned long *) bsp;
1449         return 0;
1450 }
1451
1452 #   define arg_finish_change(tcp, state)        0
1453
1454 #   ifdef SYS_fork
1455 static int
1456 get_arg0 (struct tcb *tcp, arg_setup_state *state, long *valp)
1457 {
1458         int ret;
1459
1460         if (ia32)
1461                 ret = upeek (tcp, PT_R11, valp);
1462         else
1463                 ret = umoven (tcp,
1464                               (unsigned long) ia64_rse_skip_regs(*state, 0),
1465                               sizeof(long), (void *) valp);
1466         return ret;
1467 }
1468
1469 static int
1470 get_arg1 (struct tcb *tcp, arg_setup_state *state, long *valp)
1471 {
1472         int ret;
1473
1474         if (ia32)
1475                 ret = upeek (tcp, PT_R9, valp);
1476         else
1477                 ret = umoven (tcp,
1478                               (unsigned long) ia64_rse_skip_regs(*state, 1),
1479                               sizeof(long), (void *) valp);
1480         return ret;
1481 }
1482 #   endif
1483
1484 static int
1485 set_arg0 (struct tcb *tcp, arg_setup_state *state, long val)
1486 {
1487         int req = PTRACE_POKEDATA;
1488         void *ap;
1489
1490         if (ia32) {
1491                 ap = (void *) (intptr_t) PT_R11;         /* r11 == EBX */
1492                 req = PTRACE_POKEUSER;
1493         } else
1494                 ap = ia64_rse_skip_regs(*state, 0);
1495         errno = 0;
1496         ptrace(req, tcp->pid, ap, val);
1497         return errno ? -1 : 0;
1498 }
1499
1500 static int
1501 set_arg1 (struct tcb *tcp, arg_setup_state *state, long val)
1502 {
1503         int req = PTRACE_POKEDATA;
1504         void *ap;
1505
1506         if (ia32) {
1507                 ap = (void *) (intptr_t) PT_R9;         /* r9 == ECX */
1508                 req = PTRACE_POKEUSER;
1509         } else
1510                 ap = ia64_rse_skip_regs(*state, 1);
1511         errno = 0;
1512         ptrace(req, tcp->pid, ap, val);
1513         return errno ? -1 : 0;
1514 }
1515
1516 /* ia64 does not return the input arguments from functions (and syscalls)
1517    according to ia64 RSE (Register Stack Engine) behavior.  */
1518
1519 #   define restore_arg0(tcp, state, val) ((void) (state), 0)
1520 #   define restore_arg1(tcp, state, val) ((void) (state), 0)
1521
1522 #  elif defined (SPARC) || defined (SPARC64)
1523
1524 typedef struct pt_regs arg_setup_state;
1525
1526 #   define arg_setup(tcp, state) \
1527     (ptrace (PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1528 #   define arg_finish_change(tcp, state) \
1529     (ptrace (PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1530
1531 #   define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1532 #   define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1533 #   define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1534 #   define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1535 #   define restore_arg0(tcp, state, val) 0
1536
1537 #  else /* other architectures */
1538
1539 #   if defined S390 || defined S390X
1540 /* Note: this is only true for the `clone' system call, which handles
1541    arguments specially.  We could as well say that its first two arguments
1542    are swapped relative to other architectures, but that would just be
1543    another #ifdef in the calls.  */
1544 #    define arg0_offset PT_GPR3
1545 #    define arg1_offset PT_ORIGGPR2
1546 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
1547 #    define restore_arg1(tcp, state, val) ((void) (state), 0)
1548 #    define arg0_index  1
1549 #    define arg1_index  0
1550 #   elif defined (ALPHA) || defined (MIPS)
1551 #    define arg0_offset REG_A0
1552 #    define arg1_offset (REG_A0+1)
1553 #   elif defined (AVR32)
1554 #    define arg0_offset (REG_R12)
1555 #    define arg1_offset (REG_R11)
1556 #   elif defined (POWERPC)
1557 #    define arg0_offset (sizeof(unsigned long)*PT_R3)
1558 #    define arg1_offset (sizeof(unsigned long)*PT_R4)
1559 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
1560 #   elif defined (HPPA)
1561 #    define arg0_offset  PT_GR26
1562 #    define arg1_offset  (PT_GR26-4)
1563 #   elif defined (X86_64)
1564 #    define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1565 #    define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1566 #   elif defined (SH)
1567 #    define arg0_offset (4*(REG_REG0+4))
1568 #    define arg1_offset (4*(REG_REG0+5))
1569 #   elif defined (SH64)
1570     /* ABI defines arg0 & 1 in r2 & r3 */
1571 #    define arg0_offset   (REG_OFFSET+16)
1572 #    define arg1_offset   (REG_OFFSET+24)
1573 #    define restore_arg0(tcp, state, val) 0
1574 #   elif defined CRISV10 || defined CRISV32
1575 #    define arg0_offset   (4*PT_R11)
1576 #    define arg1_offset   (4*PT_ORIG_R10)
1577 #    define restore_arg0(tcp, state, val) 0
1578 #    define restore_arg1(tcp, state, val) 0
1579 #    define arg0_index   1
1580 #    define arg1_index   0
1581 #   else
1582 #    define arg0_offset 0
1583 #    define arg1_offset 4
1584 #    if defined ARM
1585 #     define restore_arg0(tcp, state, val) 0
1586 #    endif
1587 #   endif
1588
1589 typedef int arg_setup_state;
1590
1591 #   define arg_setup(tcp, state) (0)
1592 #   define arg_finish_change(tcp, state)        0
1593 #   define get_arg0(tcp, cookie, valp) \
1594     (upeek ((tcp), arg0_offset, (valp)))
1595 #   define get_arg1(tcp, cookie, valp) \
1596     (upeek ((tcp), arg1_offset, (valp)))
1597
1598 static int
1599 set_arg0 (struct tcb *tcp, void *cookie, long val)
1600 {
1601         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1602 }
1603
1604 static int
1605 set_arg1 (struct tcb *tcp, void *cookie, long val)
1606 {
1607         return ptrace (PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1608 }
1609
1610 #  endif /* architectures */
1611
1612 #  ifndef restore_arg0
1613 #   define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1614 #  endif
1615 #  ifndef restore_arg1
1616 #   define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1617 #  endif
1618
1619 #  ifndef arg0_index
1620 #   define arg0_index 0
1621 #   define arg1_index 1
1622 #  endif
1623
1624 int
1625 setbpt(struct tcb *tcp)
1626 {
1627         static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1628         arg_setup_state state;
1629
1630         if (tcp->flags & TCB_BPTSET) {
1631                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1632                 return -1;
1633         }
1634
1635         /*
1636          * It's a silly kludge to initialize this with a search at runtime.
1637          * But it's better than maintaining another magic thing in the
1638          * godforsaken tables.
1639          */
1640         if (clone_scno[current_personality] == 0) {
1641                 int i;
1642                 for (i = 0; i < nsyscalls; ++i)
1643                         if (sysent[i].sys_func == sys_clone) {
1644                                 clone_scno[current_personality] = i;
1645                                 break;
1646                         }
1647         }
1648
1649         switch (known_scno(tcp)) {
1650 #  ifdef SYS_vfork
1651         case SYS_vfork:
1652 #  endif
1653 #  ifdef SYS_fork
1654         case SYS_fork:
1655 #  endif
1656 #  if defined SYS_fork || defined SYS_vfork
1657                 if (arg_setup (tcp, &state) < 0
1658                     || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
1659                     || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
1660                     || change_syscall(tcp, clone_scno[current_personality]) < 0
1661                     || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1662                     || set_arg1 (tcp, &state, 0) < 0
1663                     || arg_finish_change (tcp, &state) < 0)
1664                         return -1;
1665                 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1666                 tcp->u_arg[arg1_index] = 0;
1667                 tcp->flags |= TCB_BPTSET;
1668                 return 0;
1669 #  endif
1670
1671         case SYS_clone:
1672 #  ifdef SYS_clone2
1673         case SYS_clone2:
1674 #  endif
1675                 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1676                    contrary to x86 SYS_vfork above.  Even on x86 we turn the
1677                    vfork semantics into plain fork - each application must not
1678                    depend on the vfork specifics according to POSIX.  We would
1679                    hang waiting for the parent resume otherwise.  We need to
1680                    clear also CLONE_VM but only in the CLONE_VFORK case as
1681                    otherwise we would break pthread_create.  */
1682
1683                 if ((arg_setup (tcp, &state) < 0
1684                     || set_arg0 (tcp, &state,
1685                                  (tcp->u_arg[arg0_index] | CLONE_PTRACE)
1686                                  & ~(tcp->u_arg[arg0_index] & CLONE_VFORK
1687                                      ? CLONE_VFORK | CLONE_VM : 0)) < 0
1688                     || arg_finish_change (tcp, &state) < 0))
1689                         return -1;
1690                 tcp->flags |= TCB_BPTSET;
1691                 tcp->inst[0] = tcp->u_arg[arg0_index];
1692                 tcp->inst[1] = tcp->u_arg[arg1_index];
1693                 return 0;
1694
1695         default:
1696                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1697                         tcp->scno, tcp->pid);
1698                 break;
1699         }
1700
1701         return -1;
1702 }
1703
1704 int
1705 clearbpt(tcp)
1706 struct tcb *tcp;
1707 {
1708         arg_setup_state state;
1709         if (arg_setup (tcp, &state) < 0
1710             || restore_arg0 (tcp, &state, tcp->inst[0]) < 0
1711             || restore_arg1 (tcp, &state, tcp->inst[1]) < 0
1712             || arg_finish_change (tcp, &state))
1713                 if (errno != ESRCH) return -1;
1714         tcp->flags &= ~TCB_BPTSET;
1715         return 0;
1716 }
1717
1718 # else /* !defined LINUX */
1719
1720 int
1721 setbpt(tcp)
1722 struct tcb *tcp;
1723 {
1724 #  ifdef LINUX
1725         DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
1726 #   if defined (SPARC) || defined (SPARC64)
1727         /* We simply use the SunOS breakpoint code. */
1728
1729         struct regs regs;
1730         unsigned long inst;
1731 #    define LOOPA       0x30800000      /* ba,a 0 */
1732
1733         if (tcp->flags & TCB_BPTSET) {
1734                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1735                 return -1;
1736         }
1737         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1738                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1739                 return -1;
1740         }
1741         tcp->baddr = regs.r_o7 + 8;
1742         errno = 0;
1743         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
1744         if(errno) {
1745                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1746                 return -1;
1747         }
1748
1749         /*
1750          * XXX - BRUTAL MODE ON
1751          * We cannot set a real BPT in the child, since it will not be
1752          * traced at the moment it will reach the trap and would probably
1753          * die with a core dump.
1754          * Thus, we are force our way in by taking out two instructions
1755          * and insert an eternal loop instead, in expectance of the SIGSTOP
1756          * generated by our PTRACE_ATTACH.
1757          * Of cause, if we evaporate ourselves in the middle of all this...
1758          */
1759         errno = 0;
1760         inst = LOOPA;
1761 #    if defined (SPARC64)
1762         inst <<= 32;
1763         inst |= (tcp->inst[0] & 0xffffffffUL);
1764 #    endif
1765         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, inst);
1766         if(errno) {
1767                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1768                 return -1;
1769         }
1770         tcp->flags |= TCB_BPTSET;
1771
1772 #   else /* !SPARC && !SPARC64 */
1773 #    ifdef IA64
1774         if (ia32) {
1775 #               define LOOP     0x0000feeb
1776                 if (tcp->flags & TCB_BPTSET) {
1777                         fprintf(stderr, "PANIC: bpt already set in pid %u\n",
1778                                 tcp->pid);
1779                         return -1;
1780                 }
1781                 if (upeek(tcp, PT_CR_IIP, &tcp->baddr) < 0)
1782                         return -1;
1783                 if (debug)
1784                         fprintf(stderr, "[%d] setting bpt at %lx\n",
1785                                 tcp->pid, tcp->baddr);
1786                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid,
1787                                       (char *) tcp->baddr, 0);
1788                 if (errno) {
1789                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1790                         return -1;
1791                 }
1792                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1793                 if (errno) {
1794                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1795                         return -1;
1796                 }
1797                 tcp->flags |= TCB_BPTSET;
1798         } else {
1799                 /*
1800                  * Our strategy here is to replace the bundle that
1801                  * contained the clone() syscall with a bundle of the
1802                  * form:
1803                  *
1804                  *      { 1: br 1b; br 1b; br 1b }
1805                  *
1806                  * This ensures that the newly forked child will loop
1807                  * endlessly until we've got a chance to attach to it.
1808                  */
1809 #                       define LOOP0    0x0000100000000017
1810 #                       define LOOP1    0x4000000000200000
1811                 unsigned long addr, ipsr;
1812                 pid_t pid;
1813
1814                 pid = tcp->pid;
1815                 if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
1816                         return -1;
1817                 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
1818                         return -1;
1819                 /* store "ri" in low two bits */
1820                 tcp->baddr = addr | ((ipsr >> 41) & 0x3);
1821
1822                 errno = 0;
1823                 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0,
1824                                       0);
1825                 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8,
1826                                       0);
1827                 if (errno) {
1828                         perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1829                         return -1;
1830                 }
1831
1832                 errno = 0;
1833                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);
1834                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);
1835                 if (errno) {
1836                         perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1837                         return -1;
1838                 }
1839                 tcp->flags |= TCB_BPTSET;
1840         }
1841 #    else /* !IA64 */
1842
1843 #     if defined (I386) || defined(X86_64)
1844 #      define LOOP      0x0000feeb
1845 #     elif defined (M68K)
1846 #      define LOOP      0x60fe0000
1847 #     elif defined (ALPHA)
1848 #      define LOOP      0xc3ffffff
1849 #     elif defined (POWERPC)
1850 #      define LOOP      0x48000000
1851 #     elif defined(ARM)
1852 #      define LOOP      0xEAFFFFFE
1853 #     elif defined(MIPS)
1854 #      define LOOP      0x1000ffff
1855 #     elif defined(S390)
1856 #      define LOOP      0xa7f40000      /* BRC 15,0 */
1857 #     elif defined(S390X)
1858 #      define LOOP   0xa7f4000000000000UL /* BRC 15,0 */
1859 #     elif defined(HPPA)
1860 #      define LOOP      0xe81f1ff7      /* b,l,n <loc>,r0 */
1861 #     elif defined(SH)
1862 #      ifdef __LITTLE_ENDIAN__
1863 #       define LOOP   0x0000affe
1864 #      else
1865 #       define LOOP   0xfeaf0000
1866 #      endif
1867 #     else
1868 #      error unknown architecture
1869 #     endif
1870
1871         if (tcp->flags & TCB_BPTSET) {
1872                 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);
1873                 return -1;
1874         }
1875 #     if defined (I386)
1876         if (upeek(tcp, 4*EIP, &tcp->baddr) < 0)
1877                 return -1;
1878 #     elif defined (X86_64)
1879         if (upeek(tcp, 8*RIP, &tcp->baddr) < 0)
1880                 return -1;
1881 #     elif defined (M68K)
1882         if (upeek(tcp, 4*PT_PC, &tcp->baddr) < 0)
1883                 return -1;
1884 #     elif defined (ALPHA)
1885         return -1;
1886 #     elif defined (ARM)
1887         return -1;
1888 #     elif defined (MIPS)
1889         return -1;              /* FIXME: I do not know what i do - Flo */
1890 #     elif defined (POWERPC)
1891         if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &tcp->baddr) < 0)
1892                 return -1;
1893 #     elif defined(S390) || defined(S390X)
1894         if (upeek(tcp,PT_PSWADDR, &tcp->baddr) < 0)
1895                 return -1;
1896 #     elif defined(HPPA)
1897         if (upeek(tcp, PT_IAOQ0, &tcp->baddr) < 0)
1898                 return -1;
1899         tcp->baddr &= ~0x03;
1900 #     elif defined(SH)
1901         if (upeek(tcp, 4*REG_PC, &tcp->baddr) < 0)
1902                 return -1;
1903 #     else
1904 #      error unknown architecture
1905 #     endif
1906         if (debug)
1907                 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);
1908         tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);
1909         if (errno) {
1910                 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");
1911                 return -1;
1912         }
1913         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);
1914         if (errno) {
1915                 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");
1916                 return -1;
1917         }
1918         tcp->flags |= TCB_BPTSET;
1919
1920 #    endif /* !IA64 */
1921 #   endif /* !SPARC && !SPARC64 */
1922 #  endif /* LINUX */
1923
1924 #  ifdef SUNOS4
1925 #   ifdef SPARC /* This code is slightly sparc specific */
1926
1927         struct regs regs;
1928 #    define BPT 0x91d02001      /* ta   1 */
1929 #    define LOOP        0x10800000      /* ba   0 */
1930 #    define LOOPA       0x30800000      /* ba,a 0 */
1931 #    define NOP 0x01000000
1932 #    if LOOPA
1933         static int loopdeloop[1] = {LOOPA};
1934 #    else
1935         static int loopdeloop[2] = {LOOP, NOP};
1936 #    endif
1937
1938         if (tcp->flags & TCB_BPTSET) {
1939                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1940                 return -1;
1941         }
1942         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1943                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1944                 return -1;
1945         }
1946         tcp->baddr = regs.r_o7 + 8;
1947         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1948                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1949                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1950                 return -1;
1951         }
1952
1953         /*
1954          * XXX - BRUTAL MODE ON
1955          * We cannot set a real BPT in the child, since it will not be
1956          * traced at the moment it will reach the trap and would probably
1957          * die with a core dump.
1958          * Thus, we are force our way in by taking out two instructions
1959          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1960          * generated by out PTRACE_ATTACH.
1961          * Of cause, if we evaporate ourselves in the middle of all this...
1962          */
1963         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1964                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1965                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1966                 return -1;
1967         }
1968         tcp->flags |= TCB_BPTSET;
1969
1970 #   endif /* SPARC */
1971 #  endif /* SUNOS4 */
1972
1973         return 0;
1974 }
1975
1976 int
1977 clearbpt(tcp)
1978 struct tcb *tcp;
1979 {
1980
1981 #  ifdef LINUX
1982         DEAD CODE HERE? WE ARE IN 'else !defined LINUX'
1983 #   if defined(I386) || defined(X86_64)
1984         long eip;
1985 #   elif defined(POWERPC)
1986         long pc;
1987 #   elif defined(M68K)
1988         long pc;
1989 #   elif defined(ALPHA)
1990         long pc;
1991 #   elif defined(HPPA)
1992         long iaoq;
1993 #   elif defined(SH)
1994         long pc;
1995 #   endif /* architecture */
1996
1997 #   if defined (SPARC) || defined (SPARC64)
1998         /* Again, we borrow the SunOS breakpoint code. */
1999         if (!(tcp->flags & TCB_BPTSET)) {
2000                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2001                 return -1;
2002         }
2003         errno = 0;
2004         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2005         if(errno) {
2006                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
2007                 return -1;
2008         }
2009         tcp->flags &= ~TCB_BPTSET;
2010 #   elif defined(IA64)
2011         if (ia32) {
2012                 unsigned long addr;
2013
2014                 if (debug)
2015                         fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
2016                 if (!(tcp->flags & TCB_BPTSET)) {
2017                         fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2018                         return -1;
2019                 }
2020                 errno = 0;
2021                 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2022                 if (errno) {
2023                         perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
2024                         return -1;
2025                 }
2026                 tcp->flags &= ~TCB_BPTSET;
2027
2028                 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
2029                         return -1;
2030                 if (addr != tcp->baddr) {
2031                         /* The breakpoint has not been reached yet.  */
2032                         if (debug)
2033                                 fprintf(stderr,
2034                                         "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2035                                                 addr, tcp->baddr);
2036                         return 0;
2037                 }
2038         } else {
2039                 unsigned long addr, ipsr;
2040                 pid_t pid;
2041
2042                 pid = tcp->pid;
2043
2044                 if (upeek(tcp, PT_CR_IPSR, &ipsr) < 0)
2045                         return -1;
2046                 if (upeek(tcp, PT_CR_IIP, &addr) < 0)
2047                         return -1;
2048
2049                 /* restore original bundle: */
2050                 errno = 0;
2051                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);
2052                 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);
2053                 if (errno) {
2054                         perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");
2055                         return -1;
2056                 }
2057
2058                 /* restore original "ri" in ipsr: */
2059                 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);
2060                 errno = 0;
2061                 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);
2062                 if (errno) {
2063                         perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");
2064                         return -1;
2065                 }
2066
2067                 tcp->flags &= ~TCB_BPTSET;
2068
2069                 if (addr != (tcp->baddr & ~0x3)) {
2070                         /* the breakpoint has not been reached yet.  */
2071                         if (debug)
2072                                 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2073                                         addr, tcp->baddr);
2074                         return 0;
2075                 }
2076         }
2077 #   else /* !IA64 && !SPARC && !SPARC64 */
2078
2079         if (debug)
2080                 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);
2081         if (!(tcp->flags & TCB_BPTSET)) {
2082                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2083                 return -1;
2084         }
2085         errno = 0;
2086         ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);
2087         if (errno) {
2088                 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");
2089                 return -1;
2090         }
2091         tcp->flags &= ~TCB_BPTSET;
2092
2093 #    ifdef I386
2094         if (upeek(tcp, 4*EIP, &eip) < 0)
2095                 return -1;
2096         if (eip != tcp->baddr) {
2097                 /* The breakpoint has not been reached yet.  */
2098                 if (debug)
2099                         fprintf(stderr,
2100                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2101                                         eip, tcp->baddr);
2102                 return 0;
2103         }
2104 #    elif defined(X86_64)
2105         if (upeek(tcp, 8*RIP, &eip) < 0)
2106                 return -1;
2107         if (eip != tcp->baddr) {
2108                 /* The breakpoint has not been reached yet.  */
2109                 if (debug)
2110                         fprintf(stderr,
2111                                 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2112                                         eip, tcp->baddr);
2113                 return 0;
2114         }
2115 #    elif defined(POWERPC)
2116         if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0)
2117                 return -1;
2118         if (pc != tcp->baddr) {
2119                 /* The breakpoint has not been reached yet.  */
2120                 if (debug)
2121                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2122                                 pc, tcp->baddr);
2123                 return 0;
2124         }
2125 #    elif defined(M68K)
2126         if (upeek(tcp, 4*PT_PC, &pc) < 0)
2127                 return -1;
2128         if (pc != tcp->baddr) {
2129                 /* The breakpoint has not been reached yet.  */
2130                 if (debug)
2131                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2132                                 pc, tcp->baddr);
2133                 return 0;
2134         }
2135 #    elif defined(ALPHA)
2136         if (upeek(tcp, REG_PC, &pc) < 0)
2137                 return -1;
2138         if (pc != tcp->baddr) {
2139                 /* The breakpoint has not been reached yet.  */
2140                 if (debug)
2141                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2142                                 pc, tcp->baddr);
2143                 return 0;
2144         }
2145 #    elif defined(HPPA)
2146         if (upeek(tcp, PT_IAOQ0, &iaoq) < 0)
2147                 return -1;
2148         iaoq &= ~0x03;
2149         if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {
2150                 /* The breakpoint has not been reached yet.  */
2151                 if (debug)
2152                         fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",
2153                                 iaoq, tcp->baddr);
2154                 return 0;
2155         }
2156         iaoq = tcp->baddr | 3;
2157         /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is
2158          * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit
2159          * has no significant effect.
2160          */
2161         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);
2162         ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);
2163 #    elif defined(SH)
2164         if (upeek(tcp, 4*REG_PC, &pc) < 0)
2165                 return -1;
2166         if (pc != tcp->baddr) {
2167                 /* The breakpoint has not been reached yet.  */
2168                 if (debug)
2169                         fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",
2170                                 pc, tcp->baddr);
2171                 return 0;
2172         }
2173
2174 #    endif /* arch */
2175 #   endif /* !SPARC && !SPARC64 && !IA64 */
2176 #  endif /* LINUX */
2177
2178 #  ifdef SUNOS4
2179 #   ifdef SPARC
2180
2181 #    if !LOOPA
2182         struct regs regs;
2183 #    endif
2184
2185         if (!(tcp->flags & TCB_BPTSET)) {
2186                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
2187                 return -1;
2188         }
2189         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
2190                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
2191                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
2192                 return -1;
2193         }
2194         tcp->flags &= ~TCB_BPTSET;
2195
2196 #    if !LOOPA
2197         /*
2198          * Since we don't have a single instruction breakpoint, we may have
2199          * to adjust the program counter after removing our `breakpoint'.
2200          */
2201         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2202                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
2203                 return -1;
2204         }
2205         if ((regs.r_pc < tcp->baddr) ||
2206                                 (regs.r_pc > tcp->baddr + 4)) {
2207                 /* The breakpoint has not been reached yet */
2208                 if (debug)
2209                         fprintf(stderr,
2210                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
2211                                         regs.r_pc, tcp->baddr);
2212                 return 0;
2213         }
2214         if (regs.r_pc != tcp->baddr)
2215                 if (debug)
2216                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
2217                                 regs.r_pc, tcp->baddr);
2218
2219         regs.r_pc = tcp->baddr;
2220         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
2221                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
2222                 return -1;
2223         }
2224 #    endif /* LOOPA */
2225 #   endif /* SPARC */
2226 #  endif /* SUNOS4 */
2227
2228         return 0;
2229 }
2230
2231 # endif /* !defined LINUX */
2232
2233 #endif /* !USE_PROCFS */
2234
2235
2236 #ifdef SUNOS4
2237
2238 static int
2239 getex(tcp, hdr)
2240 struct tcb *tcp;
2241 struct exec *hdr;
2242 {
2243         int n;
2244
2245         for (n = 0; n < sizeof *hdr; n += 4) {
2246                 long res;
2247                 if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
2248                         return -1;
2249                 memcpy(((char *) hdr) + n, &res, 4);
2250         }
2251         if (debug) {
2252                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
2253                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
2254                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
2255                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
2256         }
2257         return 0;
2258 }
2259
2260 int
2261 fixvfork(tcp)
2262 struct tcb *tcp;
2263 {
2264         int pid = tcp->pid;
2265         /*
2266          * Change `vfork' in a freshly exec'ed dynamically linked
2267          * executable's (internal) symbol table to plain old `fork'
2268          */
2269
2270         struct exec hdr;
2271         struct link_dynamic dyn;
2272         struct link_dynamic_2 ld;
2273         char *strtab, *cp;
2274
2275         if (getex(tcp, &hdr) < 0)
2276                 return -1;
2277         if (!hdr.a_dynamic)
2278                 return -1;
2279
2280         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
2281                 fprintf(stderr, "Cannot read DYNAMIC\n");
2282                 return -1;
2283         }
2284         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
2285                 fprintf(stderr, "Cannot read link_dynamic_2\n");
2286                 return -1;
2287         }
2288         if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {
2289                 fprintf(stderr, "out of memory\n");
2290                 return -1;
2291         }
2292         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2293                                         (int)ld.ld_symb_size, strtab) < 0)
2294                 goto err;
2295
2296 # if 0
2297         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2298                 fprintf(stderr, "[symbol: %s]\n", cp);
2299                 cp += strlen(cp)+1;
2300         }
2301         return 0;
2302 # endif
2303         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
2304                 if (strcmp(cp, "_vfork") == 0) {
2305                         if (debug)
2306                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
2307                         strcpy(cp, "_fork");
2308                         break;
2309                 }
2310                 cp += strlen(cp)+1;
2311         }
2312         if (cp < strtab + ld.ld_symb_size)
2313                 /*
2314                  * Write entire symbol table back to avoid
2315                  * memory alignment bugs in ptrace
2316                  */
2317                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
2318                                         (int)ld.ld_symb_size, strtab) < 0)
2319                         goto err;
2320
2321         free(strtab);
2322         return 0;
2323
2324 err:
2325         free(strtab);
2326         return -1;
2327 }
2328
2329 #endif /* SUNOS4 */