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