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