]> granicus.if.org Git - strace/blob - util.c
75a449dc8c78406039ae24d2ee9b213d1326c791
[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 int
97 tv_nz(struct timeval *a)
98 {
99         return a->tv_sec || a->tv_usec;
100 }
101
102 int
103 tv_cmp(struct timeval *a, struct timeval *b)
104 {
105         if (a->tv_sec < b->tv_sec
106             || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec))
107                 return -1;
108         if (a->tv_sec > b->tv_sec
109             || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec))
110                 return 1;
111         return 0;
112 }
113
114 double
115 tv_float(struct timeval *tv)
116 {
117         return tv->tv_sec + tv->tv_usec/1000000.0;
118 }
119
120 void
121 tv_add(struct timeval *tv, struct timeval *a, struct timeval *b)
122 {
123         tv->tv_sec = a->tv_sec + b->tv_sec;
124         tv->tv_usec = a->tv_usec + b->tv_usec;
125         if (tv->tv_usec >= 1000000) {
126                 tv->tv_sec++;
127                 tv->tv_usec -= 1000000;
128         }
129 }
130
131 void
132 tv_sub(struct timeval *tv, struct timeval *a, struct timeval *b)
133 {
134         tv->tv_sec = a->tv_sec - b->tv_sec;
135         tv->tv_usec = a->tv_usec - b->tv_usec;
136         if (((long) tv->tv_usec) < 0) {
137                 tv->tv_sec--;
138                 tv->tv_usec += 1000000;
139         }
140 }
141
142 void
143 tv_div(struct timeval *tv, struct timeval *a, int n)
144 {
145         tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n;
146         tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000;
147         tv->tv_usec %= 1000000;
148 }
149
150 void
151 tv_mul(struct timeval *tv, struct timeval *a, int n)
152 {
153         tv->tv_usec = a->tv_usec * n;
154         tv->tv_sec = a->tv_sec * n + tv->tv_usec / 1000000;
155         tv->tv_usec %= 1000000;
156 }
157
158 const char *
159 xlookup(const struct xlat *xlat, int val)
160 {
161         for (; xlat->str != NULL; xlat++)
162                 if (xlat->val == val)
163                         return xlat->str;
164         return NULL;
165 }
166
167 char *
168 stpcpy(char *dst, const char *src)
169 {
170         while ((*dst = *src++) != '\0')
171                 dst++;
172         return dst;
173 }
174
175 /*
176  * Generic ptrace wrapper which tracks ESRCH errors
177  * by setting tcp->ptrace_errno to ESRCH.
178  *
179  * We assume that ESRCH indicates likely process death (SIGKILL?),
180  * modulo bugs where process somehow ended up not stopped.
181  * Unfortunately kernel uses ESRCH for that case too. Oh well.
182  *
183  * Currently used by upeek() only.
184  * TODO: use this in all other ptrace() calls while decoding.
185  */
186 long
187 do_ptrace(int request, struct tcb *tcp, void *addr, void *data)
188 {
189         long l;
190
191         errno = 0;
192         l = ptrace(request, tcp->pid, addr, (long) data);
193         /* Non-ESRCH errors might be our invalid reg/mem accesses,
194          * we do not record them. */
195         if (errno == ESRCH)
196                 tcp->ptrace_errno = ESRCH;
197         return l;
198 }
199
200 /*
201  * Used when we want to unblock stopped traced process.
202  * Should be only used with PTRACE_CONT, PTRACE_DETACH and PTRACE_SYSCALL.
203  * Returns 0 on success or if error was ESRCH
204  * (presumably process was killed while we talk to it).
205  * Otherwise prints error message and returns -1.
206  */
207 int
208 ptrace_restart(int op, struct tcb *tcp, int sig)
209 {
210         int err;
211         const char *msg;
212
213         errno = 0;
214         ptrace(op, tcp->pid, (void *) 1, (long) sig);
215         err = errno;
216         if (!err || err == ESRCH)
217                 return 0;
218
219         tcp->ptrace_errno = err;
220         msg = "SYSCALL";
221         if (op == PTRACE_CONT)
222                 msg = "CONT";
223         if (op == PTRACE_DETACH)
224                 msg = "DETACH";
225         fprintf(stderr, "strace: ptrace(PTRACE_%s,1,%d): %s\n",
226                         msg, sig, strerror(err));
227         return -1;
228 }
229
230 /*
231  * Print entry in struct xlat table, if there.
232  */
233 void
234 printxval(const struct xlat *xlat, int val, const char *dflt)
235 {
236         const char *str = xlookup(xlat, val);
237
238         if (str)
239                 tprintf("%s", str);
240         else
241                 tprintf("%#x /* %s */", val, dflt);
242 }
243
244 #if HAVE_LONG_LONG
245 /*
246  * Print 64bit argument at position llarg and return the index of the next
247  * argument.
248  */
249 int
250 printllval(struct tcb *tcp, const char *format, int llarg)
251 {
252 # if defined(FREEBSD) \
253      || (defined(LINUX) && defined(POWERPC) && !defined(POWERPC64)) \
254      || defined(LINUX_MIPSO32) \
255      || defined(__ARM_EABI__)
256         /* Align 64bit argument to 64bit boundary.  */
257         llarg = (llarg + 1) & 0x1e;
258 # endif
259 # if defined LINUX && (defined X86_64 || defined POWERPC64)
260         if (current_personality == 0) {
261                 tprintf(format, tcp->u_arg[llarg]);
262                 llarg++;
263         } else {
264 #  ifdef POWERPC64
265                 /* Align 64bit argument to 64bit boundary.  */
266                 llarg = (llarg + 1) & 0x1e;
267 #  endif
268                 tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
269                 llarg += 2;
270         }
271 # elif defined IA64 || defined ALPHA
272         tprintf(format, tcp->u_arg[llarg]);
273         llarg++;
274 # elif defined LINUX_MIPSN32
275         tprintf(format, tcp->ext_arg[llarg]);
276         llarg++;
277 # else
278         tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
279         llarg += 2;
280 # endif
281         return llarg;
282 }
283 #endif
284
285 /*
286  * Interpret `xlat' as an array of flags
287  * print the entries whose bits are on in `flags'
288  * return # of flags printed.
289  */
290 void
291 addflags(const struct xlat *xlat, int flags)
292 {
293         for (; xlat->str; xlat++) {
294                 if (xlat->val && (flags & xlat->val) == xlat->val) {
295                         tprintf("|%s", xlat->str);
296                         flags &= ~xlat->val;
297                 }
298         }
299         if (flags) {
300                 tprintf("|%#x", flags);
301         }
302 }
303
304 /*
305  * Interpret `xlat' as an array of flags.
306  * Print to static string the entries whose bits are on in `flags'
307  * Return static string.
308  */
309 const char *
310 sprintflags(const char *prefix, const struct xlat *xlat, int flags)
311 {
312         static char outstr[1024];
313         char *outptr;
314         int found = 0;
315
316         outptr = stpcpy(outstr, prefix);
317
318         for (; xlat->str; xlat++) {
319                 if ((flags & xlat->val) == xlat->val) {
320                         if (found)
321                                 *outptr++ = '|';
322                         outptr = stpcpy(outptr, xlat->str);
323                         flags &= ~xlat->val;
324                         found = 1;
325                 }
326         }
327         if (flags) {
328                 if (found)
329                         *outptr++ = '|';
330                 outptr += sprintf(outptr, "%#x", flags);
331         }
332
333         return outstr;
334 }
335
336 int
337 printflags(const struct xlat *xlat, int flags, const char *dflt)
338 {
339         int n;
340         const char *sep;
341
342         if (flags == 0 && xlat->val == 0) {
343                 tprintf("%s", xlat->str);
344                 return 1;
345         }
346
347         sep = "";
348         for (n = 0; xlat->str; xlat++) {
349                 if (xlat->val && (flags & xlat->val) == xlat->val) {
350                         tprintf("%s%s", sep, xlat->str);
351                         flags &= ~xlat->val;
352                         sep = "|";
353                         n++;
354                 }
355         }
356
357         if (n) {
358                 if (flags) {
359                         tprintf("%s%#x", sep, flags);
360                         n++;
361                 }
362         } else {
363                 if (flags) {
364                         tprintf("%#x", flags);
365                         if (dflt)
366                                 tprintf(" /* %s */", dflt);
367                 } else {
368                         if (dflt)
369                                 tprintf("0");
370                 }
371         }
372
373         return n;
374 }
375
376 void
377 printnum(struct tcb *tcp, long addr, const char *fmt)
378 {
379         long num;
380
381         if (!addr) {
382                 tprintf("NULL");
383                 return;
384         }
385         if (umove(tcp, addr, &num) < 0) {
386                 tprintf("%#lx", addr);
387                 return;
388         }
389         tprintf("[");
390         tprintf(fmt, num);
391         tprintf("]");
392 }
393
394 void
395 printnum_int(struct tcb *tcp, long addr, const char *fmt)
396 {
397         int num;
398
399         if (!addr) {
400                 tprintf("NULL");
401                 return;
402         }
403         if (umove(tcp, addr, &num) < 0) {
404                 tprintf("%#lx", addr);
405                 return;
406         }
407         tprintf("[");
408         tprintf(fmt, num);
409         tprintf("]");
410 }
411
412 void
413 printfd(struct tcb *tcp, int fd)
414 {
415         const char *p;
416
417         if (show_fd_path && (p = getfdpath(tcp, fd)))
418                 tprintf("%d<%s>", fd, p);
419         else
420                 tprintf("%d", fd);
421 }
422
423 void
424 printuid(const char *text, unsigned long uid)
425 {
426         tprintf("%s", text);
427         tprintf((uid == -1) ? "%ld" : "%lu", uid);
428 }
429
430 static char path[MAXPATHLEN + 1];
431
432 /*
433  * Quote string `instr' of length `size'
434  * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
435  * If `len' < 0, treat `instr' as a NUL-terminated string
436  * and quote at most (`size' - 1) bytes.
437  */
438 static int
439 string_quote(const char *instr, char *outstr, int len, int size)
440 {
441         const unsigned char *ustr = (const unsigned char *) instr;
442         char *s = outstr;
443         int usehex, c, i, eol;
444
445         eol = 0x100; /* this can never match a char */
446         if (len < 0) {
447                 size--;
448                 eol = '\0';
449         }
450
451         usehex = 0;
452         if (xflag > 1)
453                 usehex = 1;
454         else if (xflag) {
455                 /* Check for presence of symbol which require
456                    to hex-quote the whole string. */
457                 for (i = 0; i < size; ++i) {
458                         c = ustr[i];
459                         /* Check for NUL-terminated string. */
460                         if (c == eol)
461                                 break;
462                         if (!isprint(c) && !isspace(c)) {
463                                 usehex = 1;
464                                 break;
465                         }
466                 }
467         }
468
469         *s++ = '\"';
470
471         if (usehex) {
472                 /* Hex-quote the whole string. */
473                 for (i = 0; i < size; ++i) {
474                         c = ustr[i];
475                         /* Check for NUL-terminated string. */
476                         if (c == eol)
477                                 goto asciz_ended;
478                         *s++ = '\\';
479                         *s++ = 'x';
480                         *s++ = "0123456789abcdef"[c >> 4];
481                         *s++ = "0123456789abcdef"[c & 0xf];
482                 }
483         } else {
484                 for (i = 0; i < size; ++i) {
485                         c = ustr[i];
486                         /* Check for NUL-terminated string. */
487                         if (c == eol)
488                                 goto asciz_ended;
489                         switch (c) {
490                                 case '\"': case '\\':
491                                         *s++ = '\\';
492                                         *s++ = c;
493                                         break;
494                                 case '\f':
495                                         *s++ = '\\';
496                                         *s++ = 'f';
497                                         break;
498                                 case '\n':
499                                         *s++ = '\\';
500                                         *s++ = 'n';
501                                         break;
502                                 case '\r':
503                                         *s++ = '\\';
504                                         *s++ = 'r';
505                                         break;
506                                 case '\t':
507                                         *s++ = '\\';
508                                         *s++ = 't';
509                                         break;
510                                 case '\v':
511                                         *s++ = '\\';
512                                         *s++ = 'v';
513                                         break;
514                                 default:
515                                         if (isprint(c))
516                                                 *s++ = c;
517                                         else {
518                                                 /* Print \octal */
519                                                 *s++ = '\\';
520                                                 if (i + 1 < size
521                                                     && ustr[i + 1] >= '0'
522                                                     && ustr[i + 1] <= '9'
523                                                 ) {
524                                                         /* Print \ooo */
525                                                         *s++ = '0' + (c >> 6);
526                                                         *s++ = '0' + ((c >> 3) & 0x7);
527                                                 } else {
528                                                         /* Print \[[o]o]o */
529                                                         if ((c >> 3) != 0) {
530                                                                 if ((c >> 6) != 0)
531                                                                         *s++ = '0' + (c >> 6);
532                                                                 *s++ = '0' + ((c >> 3) & 0x7);
533                                                         }
534                                                 }
535                                                 *s++ = '0' + (c & 0x7);
536                                         }
537                                         break;
538                         }
539                 }
540         }
541
542         *s++ = '\"';
543         *s = '\0';
544
545         /* Return zero if we printed entire ASCIZ string (didn't truncate it) */
546         if (len < 0 && ustr[i] == '\0') {
547                 /* We didn't see NUL yet (otherwise we'd jump to 'asciz_ended')
548                  * but next char is NUL.
549                  */
550                 return 0;
551         }
552
553         return 1;
554
555  asciz_ended:
556         *s++ = '\"';
557         *s = '\0';
558         /* Return zero: we printed entire ASCIZ string (didn't truncate it) */
559         return 0;
560 }
561
562 /*
563  * Print path string specified by address `addr' and length `n'.
564  * If path length exceeds `n', append `...' to the output.
565  */
566 void
567 printpathn(struct tcb *tcp, long addr, int n)
568 {
569         if (!addr) {
570                 tprintf("NULL");
571                 return;
572         }
573
574         /* Cap path length to the path buffer size,
575            and NUL-terminate the buffer. */
576         if (n > sizeof path - 1)
577                 n = sizeof path - 1;
578         path[n] = '\0';
579
580         /* Fetch one byte more to find out whether path length > n. */
581         if (umovestr(tcp, addr, n + 1, path) < 0)
582                 tprintf("%#lx", addr);
583         else {
584                 static char outstr[4*(sizeof path - 1) + sizeof "\"...\""];
585                 const char *fmt;
586                 int trunc = (path[n] != '\0');
587
588                 if (trunc)
589                         path[n] = '\0';
590                 string_quote(path, outstr, -1, n + 1);
591                 fmt = "%s";
592                 if (trunc)
593                         fmt = "%s...";
594                 tprintf(fmt, outstr);
595         }
596 }
597
598 void
599 printpath(struct tcb *tcp, long addr)
600 {
601         printpathn(tcp, addr, sizeof path - 1);
602 }
603
604 /*
605  * Print string specified by address `addr' and length `len'.
606  * If `len' < 0, treat the string as a NUL-terminated string.
607  * If string length exceeds `max_strlen', append `...' to the output.
608  */
609 void
610 printstr(struct tcb *tcp, long addr, int len)
611 {
612         static char *str = NULL;
613         static char *outstr;
614         int size;
615         const char *fmt;
616
617         if (!addr) {
618                 tprintf("NULL");
619                 return;
620         }
621         /* Allocate static buffers if they are not allocated yet. */
622         if (!str) {
623                 str = malloc(max_strlen + 1);
624                 if (!str)
625                         die_out_of_memory();
626         }
627         if (!outstr) {
628                 outstr = malloc(4 * max_strlen + sizeof "\"...\"");
629                 if (!outstr)
630                         die_out_of_memory();
631         }
632
633         if (len < 0) {
634                 /*
635                  * Treat as a NUL-terminated string: fetch one byte more
636                  * because string_quote() quotes one byte less.
637                  */
638                 size = max_strlen + 1;
639                 str[max_strlen] = '\0';
640         /* FIXME! umovestr can overwrite the '\0' stored above??? */
641                 if (umovestr(tcp, addr, size, str) < 0) {
642                         tprintf("%#lx", addr);
643                         return;
644                 }
645         }
646         else {
647                 size = MIN(len, max_strlen);
648                 if (umoven(tcp, addr, size, str) < 0) {
649                         tprintf("%#lx", addr);
650                         return;
651                 }
652         }
653
654         fmt = "%s";
655         if (string_quote(str, outstr, len, size) &&
656             (len < 0 || len > max_strlen))
657                 fmt = "%s...";
658
659         tprintf(fmt, outstr);
660 }
661
662 #if HAVE_SYS_UIO_H
663 void
664 dumpiov(struct tcb *tcp, int len, long addr)
665 {
666 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
667         union {
668                 struct { u_int32_t base; u_int32_t len; } *iov32;
669                 struct { u_int64_t base; u_int64_t len; } *iov64;
670         } iovu;
671 #define iov iovu.iov64
672 #define sizeof_iov \
673   (personality_wordsize[current_personality] == 4 \
674    ? sizeof(*iovu.iov32) : sizeof(*iovu.iov64))
675 #define iov_iov_base(i) \
676   (personality_wordsize[current_personality] == 4 \
677    ? (u_int64_t) iovu.iov32[i].base : iovu.iov64[i].base)
678 #define iov_iov_len(i) \
679   (personality_wordsize[current_personality] == 4 \
680    ? (u_int64_t) iovu.iov32[i].len : iovu.iov64[i].len)
681 #else
682         struct iovec *iov;
683 #define sizeof_iov sizeof(*iov)
684 #define iov_iov_base(i) iov[i].iov_base
685 #define iov_iov_len(i) iov[i].iov_len
686 #endif
687         int i;
688         unsigned long size;
689
690         size = sizeof_iov * (unsigned long) len;
691         if (size / sizeof_iov != len /* overflow? */
692             || (iov = malloc(size)) == NULL) {
693                 die_out_of_memory();
694         }
695         if (umoven(tcp, addr, size, (char *) iov) >= 0) {
696                 for (i = 0; i < len; i++) {
697                         /* include the buffer number to make it easy to
698                          * match up the trace with the source */
699                         tprintf(" * %lu bytes in buffer %d\n",
700                                 (unsigned long)iov_iov_len(i), i);
701                         dumpstr(tcp, (long) iov_iov_base(i),
702                                 iov_iov_len(i));
703                 }
704         }
705         free((char *) iov);
706 #undef sizeof_iov
707 #undef iov_iov_base
708 #undef iov_iov_len
709 #undef iov
710 }
711 #endif
712
713 void
714 dumpstr(struct tcb *tcp, long addr, int len)
715 {
716         static int strsize = -1;
717         static unsigned char *str;
718         char *s;
719         int i, j;
720
721         if (strsize < len) {
722                 free(str);
723                 str = malloc(len);
724                 if (!str)
725                         die_out_of_memory();
726                 strsize = len;
727         }
728
729         if (umoven(tcp, addr, len, (char *) str) < 0)
730                 return;
731
732         for (i = 0; i < len; i += 16) {
733                 char outstr[80];
734
735                 s = outstr;
736                 sprintf(s, " | %05x ", i);
737                 s += 9;
738                 for (j = 0; j < 16; j++) {
739                         if (j == 8)
740                                 *s++ = ' ';
741                         if (i + j < len) {
742                                 sprintf(s, " %02x", str[i + j]);
743                                 s += 3;
744                         }
745                         else {
746                                 *s++ = ' '; *s++ = ' '; *s++ = ' ';
747                         }
748                 }
749                 *s++ = ' '; *s++ = ' ';
750                 for (j = 0; j < 16; j++) {
751                         if (j == 8)
752                                 *s++ = ' ';
753                         if (i + j < len) {
754                                 if (isprint(str[i + j]))
755                                         *s++ = str[i + j];
756                                 else
757                                         *s++ = '.';
758                         }
759                         else
760                                 *s++ = ' ';
761                 }
762                 tprintf("%s |\n", outstr);
763         }
764 }
765
766 #define PAGMASK (~(PAGSIZ - 1))
767 /*
768  * move `len' bytes of data from process `pid'
769  * at address `addr' to our space at `laddr'
770  */
771 int
772 umoven(struct tcb *tcp, long addr, int len, char *laddr)
773 {
774 #ifdef LINUX
775         int pid = tcp->pid;
776         int n, m;
777         int started = 0;
778         union {
779                 long val;
780                 char x[sizeof(long)];
781         } u;
782
783         if (addr & (sizeof(long) - 1)) {
784                 /* addr not a multiple of sizeof(long) */
785                 n = addr - (addr & -sizeof(long)); /* residue */
786                 addr &= -sizeof(long); /* residue */
787                 errno = 0;
788                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
789                 if (errno) {
790                         if (started && (errno==EPERM || errno==EIO)) {
791                                 /* Ran into 'end of memory' - stupid "printpath" */
792                                 return 0;
793                         }
794                         /* But if not started, we had a bogus address. */
795                         if (addr != 0 && errno != EIO && errno != ESRCH)
796                                 perror("ptrace: umoven");
797                         return -1;
798                 }
799                 started = 1;
800                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
801                 addr += sizeof(long), laddr += m, len -= m;
802         }
803         while (len) {
804                 errno = 0;
805                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
806                 if (errno) {
807                         if (started && (errno==EPERM || errno==EIO)) {
808                                 /* Ran into 'end of memory' - stupid "printpath" */
809                                 return 0;
810                         }
811                         if (addr != 0 && errno != EIO && errno != ESRCH)
812                                 perror("ptrace: umoven");
813                         return -1;
814                 }
815                 started = 1;
816                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
817                 addr += sizeof(long), laddr += m, len -= m;
818         }
819 #endif /* LINUX */
820
821 #ifdef SUNOS4
822         int pid = tcp->pid;
823         int n;
824
825         while (len) {
826                 n = MIN(len, PAGSIZ);
827                 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
828                 if (ptrace(PTRACE_READDATA, pid,
829                            (char *) addr, len, laddr) < 0) {
830                         if (errno != ESRCH) {
831                                 perror("umoven: ptrace(PTRACE_READDATA, ...)");
832                                 abort();
833                         }
834                         return -1;
835                 }
836                 len -= n;
837                 addr += n;
838                 laddr += n;
839         }
840 #endif /* SUNOS4 */
841
842 #ifdef USE_PROCFS
843 #ifdef HAVE_MP_PROCFS
844         int fd = tcp->pfd_as;
845 #else
846         int fd = tcp->pfd;
847 #endif
848         lseek(fd, addr, SEEK_SET);
849         if (read(fd, laddr, len) == -1)
850                 return -1;
851 #endif /* USE_PROCFS */
852
853         return 0;
854 }
855
856 /*
857  * like `umove' but make the additional effort of looking
858  * for a terminating zero byte.
859  */
860 int
861 umovestr(struct tcb *tcp, long addr, int len, char *laddr)
862 {
863 #ifdef USE_PROCFS
864 #ifdef HAVE_MP_PROCFS
865         int fd = tcp->pfd_as;
866 #else
867         int fd = tcp->pfd;
868 #endif
869         /* Some systems (e.g. FreeBSD) can be upset if we read off the
870            end of valid memory,  avoid this by trying to read up
871            to page boundaries.  But we don't know what a page is (and
872            getpagesize(2) (if it exists) doesn't necessarily return
873            hardware page size).  Assume all pages >= 1024 (a-historical
874            I know) */
875
876         int page = 1024;        /* How to find this? */
877         int move = page - (addr & (page - 1));
878         int left = len;
879
880         lseek(fd, addr, SEEK_SET);
881
882         while (left) {
883                 if (move > left)
884                         move = left;
885                 move = read(fd, laddr, move);
886                 if (move <= 0)
887                         return left != len ? 0 : -1;
888                 if (memchr(laddr, 0, move))
889                         break;
890                 left -= move;
891                 laddr += move;
892                 addr += move;
893                 move = page;
894         }
895 #else /* !USE_PROCFS */
896         int started = 0;
897         int pid = tcp->pid;
898         int i, n, m;
899         union {
900                 long val;
901                 char x[sizeof(long)];
902         } u;
903
904         if (addr & (sizeof(long) - 1)) {
905                 /* addr not a multiple of sizeof(long) */
906                 n = addr - (addr & -sizeof(long)); /* residue */
907                 addr &= -sizeof(long); /* residue */
908                 errno = 0;
909                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
910                 if (errno) {
911                         if (started && (errno==EPERM || errno==EIO)) {
912                                 /* Ran into 'end of memory' - stupid "printpath" */
913                                 return 0;
914                         }
915                         if (addr != 0 && errno != EIO && errno != ESRCH)
916                                 perror("umovestr");
917                         return -1;
918                 }
919                 started = 1;
920                 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n, len));
921                 while (n & (sizeof(long) - 1))
922                         if (u.x[n++] == '\0')
923                                 return 0;
924                 addr += sizeof(long), laddr += m, len -= m;
925         }
926         while (len) {
927                 errno = 0;
928                 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
929                 if (errno) {
930                         if (started && (errno==EPERM || errno==EIO)) {
931                                 /* Ran into 'end of memory' - stupid "printpath" */
932                                 return 0;
933                         }
934                         if (addr != 0 && errno != EIO && errno != ESRCH)
935                                 perror("umovestr");
936                         return -1;
937                 }
938                 started = 1;
939                 memcpy(laddr, u.x, m = MIN(sizeof(long), len));
940                 for (i = 0; i < sizeof(long); i++)
941                         if (u.x[i] == '\0')
942                                 return 0;
943
944                 addr += sizeof(long), laddr += m, len -= m;
945         }
946 #endif /* !USE_PROCFS */
947         return 0;
948 }
949
950 #ifdef LINUX
951 # if !defined (SPARC) && !defined(SPARC64)
952 #  define PTRACE_WRITETEXT      101
953 #  define PTRACE_WRITEDATA      102
954 # endif /* !SPARC && !SPARC64 */
955 #endif /* LINUX */
956
957 #ifdef SUNOS4
958
959 static int
960 uload(int cmd, int pid, long addr, int len, char *laddr)
961 {
962         int peek, poke;
963         int n, m;
964         union {
965                 long val;
966                 char x[sizeof(long)];
967         } u;
968
969         if (cmd == PTRACE_WRITETEXT) {
970                 peek = PTRACE_PEEKTEXT;
971                 poke = PTRACE_POKETEXT;
972         }
973         else {
974                 peek = PTRACE_PEEKDATA;
975                 poke = PTRACE_POKEDATA;
976         }
977         if (addr & (sizeof(long) - 1)) {
978                 /* addr not a multiple of sizeof(long) */
979                 n = addr - (addr & -sizeof(long)); /* residue */
980                 addr &= -sizeof(long);
981                 errno = 0;
982                 u.val = ptrace(peek, pid, (char *) addr, 0);
983                 if (errno) {
984                         perror("uload: POKE");
985                         return -1;
986                 }
987                 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len));
988                 if (ptrace(poke, pid, (char *)addr, u.val) < 0) {
989                         perror("uload: POKE");
990                         return -1;
991                 }
992                 addr += sizeof(long), laddr += m, len -= m;
993         }
994         while (len) {
995                 if (len < sizeof(long))
996                         u.val = ptrace(peek, pid, (char *) addr, 0);
997                 memcpy(u.x, laddr, m = MIN(sizeof(long), len));
998                 if (ptrace(poke, pid, (char *) addr, u.val) < 0) {
999                         perror("uload: POKE");
1000                         return -1;
1001                 }
1002                 addr += sizeof(long), laddr += m, len -= m;
1003         }
1004         return 0;
1005 }
1006
1007 int
1008 tload(int pid, int addr, int len, char *laddr)
1009 {
1010         return uload(PTRACE_WRITETEXT, pid, addr, len, laddr);
1011 }
1012
1013 int
1014 dload(int pid, int addr, int len, char *laddr)
1015 {
1016         return uload(PTRACE_WRITEDATA, pid, addr, len, laddr);
1017 }
1018
1019 #endif /* SUNOS4 */
1020
1021 #ifndef USE_PROCFS
1022
1023 int
1024 upeek(struct tcb *tcp, long off, long *res)
1025 {
1026         long val;
1027
1028 # ifdef SUNOS4_KERNEL_ARCH_KLUDGE
1029         {
1030                 static int is_sun4m = -1;
1031                 struct utsname name;
1032
1033                 /* Round up the usual suspects. */
1034                 if (is_sun4m == -1) {
1035                         if (uname(&name) < 0) {
1036                                 perror("upeek: uname?");
1037                                 exit(1);
1038                         }
1039                         is_sun4m = strcmp(name.machine, "sun4m") == 0;
1040                         if (is_sun4m) {
1041                                 const struct xlat *x;
1042
1043                                 for (x = struct_user_offsets; x->str; x++)
1044                                         x->val += 1024;
1045                         }
1046                 }
1047                 if (is_sun4m)
1048                         off += 1024;
1049         }
1050 # endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
1051         errno = 0;
1052         val = do_ptrace(PTRACE_PEEKUSER, tcp, (char *) off, 0);
1053         if (val == -1 && errno) {
1054                 if (errno != ESRCH) {
1055                         char buf[60];
1056                         sprintf(buf, "upeek: ptrace(PTRACE_PEEKUSER,%d,%lu,0)", tcp->pid, off);
1057                         perror(buf);
1058                 }
1059                 return -1;
1060         }
1061         *res = val;
1062         return 0;
1063 }
1064
1065 #endif /* !USE_PROCFS */
1066
1067 void
1068 printcall(struct tcb *tcp)
1069 {
1070 #define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
1071                            sizeof(long) == 8 ? "[????????????????] " : \
1072                            NULL /* crash */)
1073
1074 #ifdef LINUX
1075 # ifdef I386
1076         long eip;
1077
1078         if (upeek(tcp, 4*EIP, &eip) < 0) {
1079                 PRINTBADPC;
1080                 return;
1081         }
1082         tprintf("[%08lx] ", eip);
1083
1084 # elif defined(S390) || defined(S390X)
1085         long psw;
1086         if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
1087                 PRINTBADPC;
1088                 return;
1089         }
1090 #  ifdef S390
1091         tprintf("[%08lx] ", psw);
1092 #  elif S390X
1093         tprintf("[%16lx] ", psw);
1094 #  endif
1095
1096 # elif defined(X86_64)
1097         long rip;
1098
1099         if (upeek(tcp, 8*RIP, &rip) < 0) {
1100                 PRINTBADPC;
1101                 return;
1102         }
1103         tprintf("[%16lx] ", rip);
1104 # elif defined(IA64)
1105         long ip;
1106
1107         if (upeek(tcp, PT_B0, &ip) < 0) {
1108                 PRINTBADPC;
1109                 return;
1110         }
1111         tprintf("[%08lx] ", ip);
1112 # elif defined(POWERPC)
1113         long pc;
1114
1115         if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
1116                 PRINTBADPC;
1117                 return;
1118         }
1119 #  ifdef POWERPC64
1120         tprintf("[%016lx] ", pc);
1121 #  else
1122         tprintf("[%08lx] ", pc);
1123 #  endif
1124 # elif defined(M68K)
1125         long pc;
1126
1127         if (upeek(tcp, 4*PT_PC, &pc) < 0) {
1128                 tprintf("[????????] ");
1129                 return;
1130         }
1131         tprintf("[%08lx] ", pc);
1132 # elif defined(ALPHA)
1133         long pc;
1134
1135         if (upeek(tcp, REG_PC, &pc) < 0) {
1136                 tprintf("[????????????????] ");
1137                 return;
1138         }
1139         tprintf("[%08lx] ", pc);
1140 # elif defined(SPARC) || defined(SPARC64)
1141         struct pt_regs regs;
1142         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1143                 PRINTBADPC;
1144                 return;
1145         }
1146 #  if defined(SPARC64)
1147         tprintf("[%08lx] ", regs.tpc);
1148 #  else
1149         tprintf("[%08lx] ", regs.pc);
1150 #  endif
1151 # elif defined(HPPA)
1152         long pc;
1153
1154         if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
1155                 tprintf("[????????] ");
1156                 return;
1157         }
1158         tprintf("[%08lx] ", pc);
1159 # elif defined(MIPS)
1160         long pc;
1161
1162         if (upeek(tcp, REG_EPC, &pc) < 0) {
1163                 tprintf("[????????] ");
1164                 return;
1165         }
1166         tprintf("[%08lx] ", pc);
1167 # elif defined(SH)
1168         long pc;
1169
1170         if (upeek(tcp, 4*REG_PC, &pc) < 0) {
1171                 tprintf("[????????] ");
1172                 return;
1173         }
1174         tprintf("[%08lx] ", pc);
1175 # elif defined(SH64)
1176         long pc;
1177
1178         if (upeek(tcp, REG_PC, &pc) < 0) {
1179                 tprintf("[????????????????] ");
1180                 return;
1181         }
1182         tprintf("[%08lx] ", pc);
1183 # elif defined(ARM)
1184         long pc;
1185
1186         if (upeek(tcp, 4*15, &pc) < 0) {
1187                 PRINTBADPC;
1188                 return;
1189         }
1190         tprintf("[%08lx] ", pc);
1191 # elif defined(AVR32)
1192         long pc;
1193
1194         if (upeek(tcp, REG_PC, &pc) < 0) {
1195                 tprintf("[????????] ");
1196                 return;
1197         }
1198         tprintf("[%08lx] ", pc);
1199 # elif defined(BFIN)
1200         long pc;
1201
1202         if (upeek(tcp, PT_PC, &pc) < 0) {
1203                 PRINTBADPC;
1204                 return;
1205         }
1206         tprintf("[%08lx] ", pc);
1207 #elif defined(CRISV10)
1208         long pc;
1209
1210         if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
1211                 PRINTBADPC;
1212                 return;
1213         }
1214         tprintf("[%08lx] ", pc);
1215 #elif defined(CRISV32)
1216         long pc;
1217
1218         if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
1219                 PRINTBADPC;
1220                 return;
1221         }
1222         tprintf("[%08lx] ", pc);
1223 # endif /* architecture */
1224 #endif /* LINUX */
1225
1226 #ifdef SUNOS4
1227         struct regs regs;
1228
1229         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) &regs, 0) < 0) {
1230                 perror("printcall: ptrace(PTRACE_GETREGS, ...)");
1231                 PRINTBADPC;
1232                 return;
1233         }
1234         tprintf("[%08x] ", regs.r_o7);
1235 #endif /* SUNOS4 */
1236
1237 #ifdef SVR4
1238         /* XXX */
1239         PRINTBADPC;
1240 #endif
1241
1242 #ifdef FREEBSD
1243         struct reg regs;
1244         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1245         tprintf("[%08x] ", regs.r_eip);
1246 #endif /* FREEBSD */
1247 }
1248
1249
1250 /*
1251  * These #if's are huge, please indent them correctly.
1252  * It's easy to get confused otherwise.
1253  */
1254 #ifndef USE_PROCFS
1255
1256 # ifdef LINUX
1257
1258 #  include "syscall.h"
1259
1260 #  include <sys/syscall.h>
1261 #  ifndef CLONE_PTRACE
1262 #   define CLONE_PTRACE    0x00002000
1263 #  endif
1264 #  ifndef CLONE_VFORK
1265 #   define CLONE_VFORK     0x00004000
1266 #  endif
1267 #  ifndef CLONE_VM
1268 #   define CLONE_VM        0x00000100
1269 #  endif
1270 #  ifndef CLONE_STOPPED
1271 #   define CLONE_STOPPED   0x02000000
1272 #  endif
1273
1274 #  ifdef IA64
1275
1276 /* We don't have fork()/vfork() syscalls on ia64 itself, but the ia32
1277    subsystem has them for x86... */
1278 #   define SYS_fork     2
1279 #   define SYS_vfork    190
1280
1281 typedef unsigned long *arg_setup_state;
1282
1283 static int
1284 arg_setup(struct tcb *tcp, arg_setup_state *state)
1285 {
1286         unsigned long cfm, sof, sol;
1287         long bsp;
1288
1289         if (ia32) {
1290                 /* Satisfy a false GCC warning.  */
1291                 *state = NULL;
1292                 return 0;
1293         }
1294
1295         if (upeek(tcp, PT_AR_BSP, &bsp) < 0)
1296                 return -1;
1297         if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1298                 return -1;
1299
1300         sof = (cfm >> 0) & 0x7f;
1301         sol = (cfm >> 7) & 0x7f;
1302         bsp = (long) ia64_rse_skip_regs((unsigned long *) bsp, -sof + sol);
1303
1304         *state = (unsigned long *) bsp;
1305         return 0;
1306 }
1307
1308 #   define arg_finish_change(tcp, state)        0
1309
1310 #   ifdef SYS_fork
1311 static int
1312 get_arg0(struct tcb *tcp, arg_setup_state *state, long *valp)
1313 {
1314         int ret;
1315
1316         if (ia32)
1317                 ret = upeek(tcp, PT_R11, valp);
1318         else
1319                 ret = umoven(tcp,
1320                               (unsigned long) ia64_rse_skip_regs(*state, 0),
1321                               sizeof(long), (void *) valp);
1322         return ret;
1323 }
1324
1325 static int
1326 get_arg1(struct tcb *tcp, arg_setup_state *state, long *valp)
1327 {
1328         int ret;
1329
1330         if (ia32)
1331                 ret = upeek(tcp, PT_R9, valp);
1332         else
1333                 ret = umoven(tcp,
1334                               (unsigned long) ia64_rse_skip_regs(*state, 1),
1335                               sizeof(long), (void *) valp);
1336         return ret;
1337 }
1338 #   endif
1339
1340 static int
1341 set_arg0(struct tcb *tcp, arg_setup_state *state, long val)
1342 {
1343         int req = PTRACE_POKEDATA;
1344         void *ap;
1345
1346         if (ia32) {
1347                 ap = (void *) (intptr_t) PT_R11;         /* r11 == EBX */
1348                 req = PTRACE_POKEUSER;
1349         } else
1350                 ap = ia64_rse_skip_regs(*state, 0);
1351         errno = 0;
1352         ptrace(req, tcp->pid, ap, val);
1353         return errno ? -1 : 0;
1354 }
1355
1356 static int
1357 set_arg1(struct tcb *tcp, arg_setup_state *state, long val)
1358 {
1359         int req = PTRACE_POKEDATA;
1360         void *ap;
1361
1362         if (ia32) {
1363                 ap = (void *) (intptr_t) PT_R9;         /* r9 == ECX */
1364                 req = PTRACE_POKEUSER;
1365         } else
1366                 ap = ia64_rse_skip_regs(*state, 1);
1367         errno = 0;
1368         ptrace(req, tcp->pid, ap, val);
1369         return errno ? -1 : 0;
1370 }
1371
1372 /* ia64 does not return the input arguments from functions (and syscalls)
1373    according to ia64 RSE (Register Stack Engine) behavior.  */
1374
1375 #   define restore_arg0(tcp, state, val) ((void) (state), 0)
1376 #   define restore_arg1(tcp, state, val) ((void) (state), 0)
1377
1378 #  elif defined (SPARC) || defined (SPARC64)
1379
1380 typedef struct pt_regs arg_setup_state;
1381
1382 #   define arg_setup(tcp, state) \
1383     (ptrace(PTRACE_GETREGS, tcp->pid, (char *) (state), 0))
1384 #   define arg_finish_change(tcp, state) \
1385     (ptrace(PTRACE_SETREGS, tcp->pid, (char *) (state), 0))
1386
1387 #   define get_arg0(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O0], 0)
1388 #   define get_arg1(tcp, state, valp) (*(valp) = (state)->u_regs[U_REG_O1], 0)
1389 #   define set_arg0(tcp, state, val) ((state)->u_regs[U_REG_O0] = (val), 0)
1390 #   define set_arg1(tcp, state, val) ((state)->u_regs[U_REG_O1] = (val), 0)
1391 #   define restore_arg0(tcp, state, val) 0
1392
1393 #  else /* other architectures */
1394
1395 #   if defined S390 || defined S390X
1396 /* Note: this is only true for the `clone' system call, which handles
1397    arguments specially.  We could as well say that its first two arguments
1398    are swapped relative to other architectures, but that would just be
1399    another #ifdef in the calls.  */
1400 #    define arg0_offset PT_GPR3
1401 #    define arg1_offset PT_ORIGGPR2
1402 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
1403 #    define restore_arg1(tcp, state, val) ((void) (state), 0)
1404 #    define arg0_index  1
1405 #    define arg1_index  0
1406 #   elif defined (ALPHA) || defined (MIPS)
1407 #    define arg0_offset REG_A0
1408 #    define arg1_offset (REG_A0+1)
1409 #   elif defined (AVR32)
1410 #    define arg0_offset (REG_R12)
1411 #    define arg1_offset (REG_R11)
1412 #   elif defined (POWERPC)
1413 #    define arg0_offset (sizeof(unsigned long)*PT_R3)
1414 #    define arg1_offset (sizeof(unsigned long)*PT_R4)
1415 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
1416 #   elif defined (HPPA)
1417 #    define arg0_offset  PT_GR26
1418 #    define arg1_offset  (PT_GR26-4)
1419 #   elif defined (X86_64)
1420 #    define arg0_offset ((long)(8*(current_personality ? RBX : RDI)))
1421 #    define arg1_offset ((long)(8*(current_personality ? RCX : RSI)))
1422 #   elif defined (SH)
1423 #    define arg0_offset (4*(REG_REG0+4))
1424 #    define arg1_offset (4*(REG_REG0+5))
1425 #   elif defined (SH64)
1426     /* ABI defines arg0 & 1 in r2 & r3 */
1427 #    define arg0_offset   (REG_OFFSET+16)
1428 #    define arg1_offset   (REG_OFFSET+24)
1429 #    define restore_arg0(tcp, state, val) 0
1430 #   elif defined CRISV10 || defined CRISV32
1431 #    define arg0_offset   (4*PT_R11)
1432 #    define arg1_offset   (4*PT_ORIG_R10)
1433 #    define restore_arg0(tcp, state, val) 0
1434 #    define restore_arg1(tcp, state, val) 0
1435 #    define arg0_index   1
1436 #    define arg1_index   0
1437 #   else
1438 #    define arg0_offset 0
1439 #    define arg1_offset 4
1440 #    if defined ARM
1441 #     define restore_arg0(tcp, state, val) 0
1442 #    endif
1443 #   endif
1444
1445 typedef int arg_setup_state;
1446
1447 #   define arg_setup(tcp, state) (0)
1448 #   define arg_finish_change(tcp, state)        0
1449 #   define get_arg0(tcp, cookie, valp) \
1450     (upeek((tcp), arg0_offset, (valp)))
1451 #   define get_arg1(tcp, cookie, valp) \
1452     (upeek((tcp), arg1_offset, (valp)))
1453
1454 static int
1455 set_arg0(struct tcb *tcp, void *cookie, long val)
1456 {
1457         return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg0_offset, val);
1458 }
1459
1460 static int
1461 set_arg1(struct tcb *tcp, void *cookie, long val)
1462 {
1463         return ptrace(PTRACE_POKEUSER, tcp->pid, (char*)arg1_offset, val);
1464 }
1465
1466 #  endif /* architectures */
1467
1468 #  ifndef restore_arg0
1469 #   define restore_arg0(tcp, state, val) set_arg0((tcp), (state), (val))
1470 #  endif
1471 #  ifndef restore_arg1
1472 #   define restore_arg1(tcp, state, val) set_arg1((tcp), (state), (val))
1473 #  endif
1474
1475 #  ifndef arg0_index
1476 #   define arg0_index 0
1477 #   define arg1_index 1
1478 #  endif
1479
1480 int
1481 setbpt(struct tcb *tcp)
1482 {
1483         static int clone_scno[SUPPORTED_PERSONALITIES] = { SYS_clone };
1484         arg_setup_state state;
1485
1486         if (tcp->flags & TCB_BPTSET) {
1487                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1488                 return -1;
1489         }
1490
1491         /*
1492          * It's a silly kludge to initialize this with a search at runtime.
1493          * But it's better than maintaining another magic thing in the
1494          * godforsaken tables.
1495          */
1496         if (clone_scno[current_personality] == 0) {
1497                 int i;
1498                 for (i = 0; i < nsyscalls; ++i)
1499                         if (sysent[i].sys_func == sys_clone) {
1500                                 clone_scno[current_personality] = i;
1501                                 break;
1502                         }
1503         }
1504
1505         switch (known_scno(tcp)) {
1506 #  ifdef SYS_vfork
1507         case SYS_vfork:
1508 #  endif
1509 #  ifdef SYS_fork
1510         case SYS_fork:
1511 #  endif
1512 #  if defined SYS_fork || defined SYS_vfork
1513                 if (arg_setup(tcp, &state) < 0
1514                     || get_arg0(tcp, &state, &tcp->inst[0]) < 0
1515                     || get_arg1(tcp, &state, &tcp->inst[1]) < 0
1516                     || change_syscall(tcp, clone_scno[current_personality]) < 0
1517                     || set_arg0(tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
1518                     || set_arg1(tcp, &state, 0) < 0
1519                     || arg_finish_change(tcp, &state) < 0)
1520                         return -1;
1521                 tcp->u_arg[arg0_index] = CLONE_PTRACE|SIGCHLD;
1522                 tcp->u_arg[arg1_index] = 0;
1523                 tcp->flags |= TCB_BPTSET;
1524                 return 0;
1525 #  endif
1526
1527         case SYS_clone: ;
1528 #  ifdef SYS_clone2
1529         case SYS_clone2: ;
1530 #  endif
1531                 /* ia64 calls directly `clone (CLONE_VFORK | CLONE_VM)'
1532                    contrary to x86 SYS_vfork above.  Even on x86 we turn the
1533                    vfork semantics into plain fork - each application must not
1534                    depend on the vfork specifics according to POSIX.  We would
1535                    hang waiting for the parent resume otherwise.  We need to
1536                    clear also CLONE_VM but only in the CLONE_VFORK case as
1537                    otherwise we would break pthread_create.  */
1538
1539                 long new_arg0 = (tcp->u_arg[arg0_index] | CLONE_PTRACE);
1540                 if (new_arg0 & CLONE_VFORK)
1541                         new_arg0 &= ~(unsigned long)(CLONE_VFORK | CLONE_VM);
1542                 if (arg_setup(tcp, &state) < 0
1543                  || set_arg0(tcp, &state, new_arg0) < 0
1544                  || arg_finish_change(tcp, &state) < 0)
1545                         return -1;
1546                 tcp->flags |= TCB_BPTSET;
1547                 tcp->inst[0] = tcp->u_arg[arg0_index];
1548                 tcp->inst[1] = tcp->u_arg[arg1_index];
1549                 return 0;
1550
1551         default:
1552                 fprintf(stderr, "PANIC: setbpt for syscall %ld on %u???\n",
1553                         tcp->scno, tcp->pid);
1554                 break;
1555         }
1556
1557         return -1;
1558 }
1559
1560 int
1561 clearbpt(struct tcb *tcp)
1562 {
1563         arg_setup_state state;
1564         if (arg_setup(tcp, &state) < 0
1565             || restore_arg0(tcp, &state, tcp->inst[0]) < 0
1566             || restore_arg1(tcp, &state, tcp->inst[1]) < 0
1567             || arg_finish_change(tcp, &state))
1568                 if (errno != ESRCH)
1569                         return -1;
1570         tcp->flags &= ~TCB_BPTSET;
1571         return 0;
1572 }
1573
1574 # else /* !defined LINUX */
1575
1576 int
1577 setbpt(struct tcb *tcp)
1578 {
1579 #  ifdef SUNOS4
1580 #   ifdef SPARC /* This code is slightly sparc specific */
1581
1582         struct regs regs;
1583 #    define BPT 0x91d02001      /* ta   1 */
1584 #    define LOOP        0x10800000      /* ba   0 */
1585 #    define LOOPA       0x30800000      /* ba,a 0 */
1586 #    define NOP 0x01000000
1587 #    if LOOPA
1588         static int loopdeloop[1] = {LOOPA};
1589 #    else
1590         static int loopdeloop[2] = {LOOP, NOP};
1591 #    endif
1592
1593         if (tcp->flags & TCB_BPTSET) {
1594                 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);
1595                 return -1;
1596         }
1597         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1598                 perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
1599                 return -1;
1600         }
1601         tcp->baddr = regs.r_o7 + 8;
1602         if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,
1603                                 sizeof tcp->inst, (char *)tcp->inst) < 0) {
1604                 perror("setbpt: ptrace(PTRACE_READTEXT, ...)");
1605                 return -1;
1606         }
1607
1608         /*
1609          * XXX - BRUTAL MODE ON
1610          * We cannot set a real BPT in the child, since it will not be
1611          * traced at the moment it will reach the trap and would probably
1612          * die with a core dump.
1613          * Thus, we are force our way in by taking out two instructions
1614          * and insert an eternal loop in stead, in expectance of the SIGSTOP
1615          * generated by out PTRACE_ATTACH.
1616          * Of cause, if we evaporate ourselves in the middle of all this...
1617          */
1618         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1619                         sizeof loopdeloop, (char *) loopdeloop) < 0) {
1620                 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");
1621                 return -1;
1622         }
1623         tcp->flags |= TCB_BPTSET;
1624
1625 #   endif /* SPARC */
1626 #  endif /* SUNOS4 */
1627
1628         return 0;
1629 }
1630
1631 int
1632 clearbpt(struct tcb *tcp)
1633 {
1634 #  ifdef SUNOS4
1635 #   ifdef SPARC
1636
1637 #    if !LOOPA
1638         struct regs regs;
1639 #    endif
1640
1641         if (!(tcp->flags & TCB_BPTSET)) {
1642                 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);
1643                 return -1;
1644         }
1645         if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,
1646                                 sizeof tcp->inst, (char *) tcp->inst) < 0) {
1647                 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");
1648                 return -1;
1649         }
1650         tcp->flags &= ~TCB_BPTSET;
1651
1652 #    if !LOOPA
1653         /*
1654          * Since we don't have a single instruction breakpoint, we may have
1655          * to adjust the program counter after removing our `breakpoint'.
1656          */
1657         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1658                 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");
1659                 return -1;
1660         }
1661         if ((regs.r_pc < tcp->baddr) ||
1662                                 (regs.r_pc > tcp->baddr + 4)) {
1663                 /* The breakpoint has not been reached yet */
1664                 if (debug)
1665                         fprintf(stderr,
1666                                 "NOTE: PC not at bpt (pc %#x baddr %#x)\n",
1667                                         regs.r_pc, tcp->baddr);
1668                 return 0;
1669         }
1670         if (regs.r_pc != tcp->baddr)
1671                 if (debug)
1672                         fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",
1673                                 regs.r_pc, tcp->baddr);
1674
1675         regs.r_pc = tcp->baddr;
1676         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {
1677                 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");
1678                 return -1;
1679         }
1680 #    endif /* LOOPA */
1681 #   endif /* SPARC */
1682 #  endif /* SUNOS4 */
1683
1684         return 0;
1685 }
1686
1687 # endif /* !defined LINUX */
1688
1689 #endif /* !USE_PROCFS */
1690
1691
1692 #ifdef SUNOS4
1693
1694 static int
1695 getex(struct tcb *tcp, struct exec *hdr)
1696 {
1697         int n;
1698
1699         for (n = 0; n < sizeof *hdr; n += 4) {
1700                 long res;
1701                 if (upeek(tcp, uoff(u_exdata) + n, &res) < 0)
1702                         return -1;
1703                 memcpy(((char *) hdr) + n, &res, 4);
1704         }
1705         if (debug) {
1706                 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",
1707                         hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);
1708                 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",
1709                         hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);
1710         }
1711         return 0;
1712 }
1713
1714 int
1715 fixvfork(struct tcb *tcp)
1716 {
1717         int pid = tcp->pid;
1718         /*
1719          * Change `vfork' in a freshly exec'ed dynamically linked
1720          * executable's (internal) symbol table to plain old `fork'
1721          */
1722
1723         struct exec hdr;
1724         struct link_dynamic dyn;
1725         struct link_dynamic_2 ld;
1726         char *strtab, *cp;
1727
1728         if (getex(tcp, &hdr) < 0)
1729                 return -1;
1730         if (!hdr.a_dynamic)
1731                 return -1;
1732
1733         if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {
1734                 fprintf(stderr, "Cannot read DYNAMIC\n");
1735                 return -1;
1736         }
1737         if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {
1738                 fprintf(stderr, "Cannot read link_dynamic_2\n");
1739                 return -1;
1740         }
1741         strtab = malloc((unsigned)ld.ld_symb_size);
1742         if (!strtab)
1743                 die_out_of_memory();
1744         if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1745                                         (int)ld.ld_symb_size, strtab) < 0)
1746                 goto err;
1747
1748         for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {
1749                 if (strcmp(cp, "_vfork") == 0) {
1750                         if (debug)
1751                                 fprintf(stderr, "fixvfork: FOUND _vfork\n");
1752                         strcpy(cp, "_fork");
1753                         break;
1754                 }
1755                 cp += strlen(cp)+1;
1756         }
1757         if (cp < strtab + ld.ld_symb_size)
1758                 /*
1759                  * Write entire symbol table back to avoid
1760                  * memory alignment bugs in ptrace
1761                  */
1762                 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),
1763                                         (int)ld.ld_symb_size, strtab) < 0)
1764                         goto err;
1765
1766         free(strtab);
1767         return 0;
1768
1769 err:
1770         free(strtab);
1771         return -1;
1772 }
1773
1774 #endif /* SUNOS4 */