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