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