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