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