]> granicus.if.org Git - strace/blob - syscall.c
.
[strace] / syscall.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 <time.h>
40 #include <errno.h>
41 #include <sys/user.h>
42 #include <sys/syscall.h>
43 #include <sys/param.h>
44
45 #if HAVE_ASM_REG_H
46 #if defined (SPARC) || defined (SPARC64)
47 #  define fpq kernel_fpq
48 #  define fq kernel_fq
49 #  define fpu kernel_fpu
50 #endif
51 #include <asm/reg.h>
52 #if defined (SPARC) || defined (SPARC64)
53 #  undef fpq
54 #  undef fq
55 #  undef fpu
56 #endif
57 #endif
58
59 #ifdef HAVE_SYS_REG_H
60 #include <sys/reg.h>
61 #ifndef PTRACE_PEEKUSR
62 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
63 #endif
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 #if defined (LINUX) && defined (SPARC64)
78 # define r_pc r_tpc
79 # undef PTRACE_GETREGS
80 # define PTRACE_GETREGS PTRACE_GETREGS64
81 # undef PTRACE_SETREGS
82 # define PTRACE_SETREGS PTRACE_SETREGS64
83 #endif /* LINUX && SPARC64 */
84
85 #if defined(LINUX) && defined(IA64)
86 # include <asm/ptrace_offsets.h>
87 # include <asm/rse.h>
88 #endif
89
90 #define NR_SYSCALL_BASE 0
91 #ifdef LINUX
92 #ifndef ERESTARTSYS
93 #define ERESTARTSYS     512
94 #endif
95 #ifndef ERESTARTNOINTR
96 #define ERESTARTNOINTR  513
97 #endif
98 #ifndef ERESTARTNOHAND
99 #define ERESTARTNOHAND  514     /* restart if no handler.. */
100 #endif
101 #ifndef ENOIOCTLCMD
102 #define ENOIOCTLCMD     515     /* No ioctl command */
103 #endif
104 #ifndef ERESTART_RESTARTBLOCK
105 #define ERESTART_RESTARTBLOCK 516       /* restart by calling sys_restart_syscall */
106 #endif
107 #ifndef NSIG
108 #define NSIG 32
109 #endif
110 #ifdef ARM
111 #undef NSIG
112 #define NSIG 32
113 #undef NR_SYSCALL_BASE
114 #define NR_SYSCALL_BASE __NR_SYSCALL_BASE
115 #endif
116 #endif /* LINUX */
117
118 #include "syscall.h"
119
120 /* Define these shorthand notations to simplify the syscallent files. */
121 #define TF TRACE_FILE
122 #define TI TRACE_IPC
123 #define TN TRACE_NETWORK
124 #define TP TRACE_PROCESS
125 #define TS TRACE_SIGNAL
126
127 static const struct sysent sysent0[] = {
128 #include "syscallent.h"
129 };
130 static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
131
132 #if SUPPORTED_PERSONALITIES >= 2
133 static const struct sysent sysent1[] = {
134 #include "syscallent1.h"
135 };
136 static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
137 #endif /* SUPPORTED_PERSONALITIES >= 2 */
138
139 #if SUPPORTED_PERSONALITIES >= 3
140 static const struct sysent sysent2[] = {
141 #include "syscallent2.h"
142 };
143 static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
144 #endif /* SUPPORTED_PERSONALITIES >= 3 */
145
146 const struct sysent *sysent;
147 int nsyscalls;
148
149 /* Now undef them since short defines cause wicked namespace pollution. */
150 #undef TF
151 #undef TI
152 #undef TN
153 #undef TP
154 #undef TS
155
156 static const char *const errnoent0[] = {
157 #include "errnoent.h"
158 };
159 static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
160
161 #if SUPPORTED_PERSONALITIES >= 2
162 static const char *const errnoent1[] = {
163 #include "errnoent1.h"
164 };
165 static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
166 #endif /* SUPPORTED_PERSONALITIES >= 2 */
167
168 #if SUPPORTED_PERSONALITIES >= 3
169 static const char *const errnoent2[] = {
170 #include "errnoent2.h"
171 };
172 static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
173 #endif /* SUPPORTED_PERSONALITIES >= 3 */
174
175 const char *const *errnoent;
176 int nerrnos;
177
178 int current_personality;
179
180 int
181 set_personality(personality)
182 int personality;
183 {
184         switch (personality) {
185         case 0:
186                 errnoent = errnoent0;
187                 nerrnos = nerrnos0;
188                 sysent = sysent0;
189                 nsyscalls = nsyscalls0;
190                 ioctlent = ioctlent0;
191                 nioctlents = nioctlents0;
192                 signalent = signalent0;
193                 nsignals = nsignals0;
194                 break;
195
196 #if SUPPORTED_PERSONALITIES >= 2
197         case 1:
198                 errnoent = errnoent1;
199                 nerrnos = nerrnos1;
200                 sysent = sysent1;
201                 nsyscalls = nsyscalls1;
202                 ioctlent = ioctlent1;
203                 nioctlents = nioctlents1;
204                 signalent = signalent1;
205                 nsignals = nsignals1;
206                 break;
207 #endif /* SUPPORTED_PERSONALITIES >= 2 */
208
209 #if SUPPORTED_PERSONALITIES >= 3
210         case 2:
211                 errnoent = errnoent2;
212                 nerrnos = nerrnos2;
213                 sysent = sysent2;
214                 nsyscalls = nsyscalls2;
215                 ioctlent = ioctlent2;
216                 nioctlents = nioctlents2;
217                 signalent = signalent2;
218                 nsignals = nsignals2;
219                 break;
220 #endif /* SUPPORTED_PERSONALITIES >= 3 */
221
222         default:
223                 return -1;
224         }
225
226         current_personality = personality;
227         return 0;
228 }
229
230 int qual_flags[MAX_QUALS];
231
232
233 struct call_counts {
234         struct timeval time;
235         int calls, errors;
236 };
237
238 static struct call_counts *counts;
239
240 static struct timeval shortest = { 1000000, 0 };
241
242 static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
243
244 static const struct qual_options {
245         int bitflag;
246         char *option_name;
247         int (*qualify)();
248         char *argument_name;
249 } qual_options[] = {
250         { QUAL_TRACE,   "trace",        qual_syscall,   "system call"   },
251         { QUAL_TRACE,   "t",            qual_syscall,   "system call"   },
252         { QUAL_ABBREV,  "abbrev",       qual_syscall,   "system call"   },
253         { QUAL_ABBREV,  "a",            qual_syscall,   "system call"   },
254         { QUAL_VERBOSE, "verbose",      qual_syscall,   "system call"   },
255         { QUAL_VERBOSE, "v",            qual_syscall,   "system call"   },
256         { QUAL_RAW,     "raw",          qual_syscall,   "system call"   },
257         { QUAL_RAW,     "x",            qual_syscall,   "system call"   },
258         { QUAL_SIGNAL,  "signal",       qual_signal,    "signal"        },
259         { QUAL_SIGNAL,  "signals",      qual_signal,    "signal"        },
260         { QUAL_SIGNAL,  "s",            qual_signal,    "signal"        },
261         { QUAL_FAULT,   "fault",        qual_fault,     "fault"         },
262         { QUAL_FAULT,   "faults",       qual_fault,     "fault"         },
263         { QUAL_FAULT,   "m",            qual_fault,     "fault"         },
264         { QUAL_READ,    "read",         qual_desc,      "descriptor"    },
265         { QUAL_READ,    "reads",        qual_desc,      "descriptor"    },
266         { QUAL_READ,    "r",            qual_desc,      "descriptor"    },
267         { QUAL_WRITE,   "write",        qual_desc,      "descriptor"    },
268         { QUAL_WRITE,   "writes",       qual_desc,      "descriptor"    },
269         { QUAL_WRITE,   "w",            qual_desc,      "descriptor"    },
270         { 0,            NULL,           NULL,           NULL            },
271 };
272
273 static void
274 qualify_one(n, opt, not)
275         int n;
276         const struct qual_options *opt;
277         int not;
278 {
279         if (not)
280                 qual_flags[n] &= ~opt->bitflag;
281         else
282                 qual_flags[n] |= opt->bitflag;
283 }
284
285 static int
286 qual_syscall(s, opt, not)
287         char *s;
288         const struct qual_options *opt;
289         int not;
290 {
291         int i;
292         int any = 0;
293
294         for (i = 0; i < nsyscalls; i++) {
295                 if (strcmp(s, sysent[i].sys_name) == 0) {
296                         qualify_one(i, opt, not);
297                         any = 1;
298                 }
299         }
300         return !any;
301 }
302
303 static int
304 qual_signal(s, opt, not)
305         char *s;
306         const struct qual_options *opt;
307         int not;
308 {
309         int i;
310         char buf[32];
311
312         if (s && *s && isdigit((unsigned char)*s)) {
313                 qualify_one(atoi(s), opt, not);
314                 return 1;
315         }
316         if (strlen(s) >= sizeof buf)
317                 return 0;
318         strcpy(buf, s);
319         s = buf;
320         for (i = 0; s[i]; i++)
321                 s[i] = toupper((unsigned char)(s[i]));
322         if (strncmp(s, "SIG", 3) == 0)
323                 s += 3;
324         for (i = 0; i <= NSIG; i++)
325                 if (strcmp(s, signame(i) + 3) == 0) {
326                         qualify_one(atoi(s), opt, not);
327                         return 1;
328                 }
329         return 0;
330 }
331
332 static int
333 qual_fault(s, opt, not)
334         char *s;
335         const struct qual_options *opt;
336         int not;
337 {
338         return -1;
339 }
340
341 static int
342 qual_desc(s, opt, not)
343         char *s;
344         const struct qual_options *opt;
345         int not;
346 {
347         if (s && *s && isdigit((unsigned char)*s)) {
348                 qualify_one(atoi(s), opt, not);
349                 return 0;
350         }
351         return -1;
352 }
353
354 static int
355 lookup_class(s)
356         char *s;
357 {
358         if (strcmp(s, "file") == 0)
359                 return TRACE_FILE;
360         if (strcmp(s, "ipc") == 0)
361                 return TRACE_IPC;
362         if (strcmp(s, "network") == 0)
363                 return TRACE_NETWORK;
364         if (strcmp(s, "process") == 0)
365                 return TRACE_PROCESS;
366         if (strcmp(s, "signal") == 0)
367                 return TRACE_SIGNAL;
368         return -1;
369 }
370
371 void
372 qualify(s)
373 char *s;
374 {
375         const struct qual_options *opt;
376         int not;
377         char *p;
378         int i, n;
379
380         opt = &qual_options[0];
381         for (i = 0; (p = qual_options[i].option_name); i++) {
382                 n = strlen(p);
383                 if (strncmp(s, p, n) == 0 && s[n] == '=') {
384                         opt = &qual_options[i];
385                         s += n + 1;
386                         break;
387                 }
388         }
389         not = 0;
390         if (*s == '!') {
391                 not = 1;
392                 s++;
393         }
394         if (strcmp(s, "none") == 0) {
395                 not = 1 - not;
396                 s = "all";
397         }
398         if (strcmp(s, "all") == 0) {
399                 for (i = 0; i < MAX_QUALS; i++) {
400                         if (not)
401                                 qual_flags[i] &= ~opt->bitflag;
402                         else
403                                 qual_flags[i] |= opt->bitflag;
404                 }
405                 return;
406         }
407         for (i = 0; i < MAX_QUALS; i++) {
408                 if (not)
409                         qual_flags[i] |= opt->bitflag;
410                 else
411                         qual_flags[i] &= ~opt->bitflag;
412         }
413         for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {
414                 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
415                         for (i = 0; i < MAX_QUALS; i++) {
416                                 if (sysent[i].sys_flags & n) {
417                                         if (not)
418                                                 qual_flags[i] &= ~opt->bitflag;
419                                         else
420                                                 qual_flags[i] |= opt->bitflag;
421                                 }
422                         }
423                         continue;
424                 }
425                 if (opt->qualify(p, opt, not)) {
426                         fprintf(stderr, "strace: invalid %s `%s'\n",
427                                 opt->argument_name, p);
428                         exit(1);
429                 }
430         }
431         return;
432 }
433
434 static void
435 dumpio(tcp)
436 struct tcb *tcp;
437 {
438         if (syserror(tcp))
439                 return;
440         if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
441                 return;
442         switch (tcp->scno + NR_SYSCALL_BASE) {
443         case SYS_read:
444 #ifdef SYS_pread64
445         case SYS_pread64:
446 #endif
447 #if defined SYS_pread && SYS_pread64 != SYS_pread
448         case SYS_pread:
449 #endif
450 #ifdef SYS_recv
451         case SYS_recv:
452 #endif
453 #ifdef SYS_recvfrom
454         case SYS_recvfrom:
455 #endif
456                 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
457                         dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
458                 break;
459         case SYS_write:
460 #ifdef SYS_pwrite64
461         case SYS_pwrite64:
462 #endif
463 #if defined SYS_pwrite && SYS_pwrite64 != SYS_pwrite
464         case SYS_pwrite:
465 #endif
466 #ifdef SYS_send
467         case SYS_send:
468 #endif
469 #ifdef SYS_sendto
470         case SYS_sendto:
471 #endif
472                 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
473                         dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
474                 break;
475 #ifdef SYS_readv
476         case SYS_readv:
477                 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
478                         dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
479                 break;
480 #endif
481 #ifdef SYS_writev
482         case SYS_writev:
483
484                 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
485                         dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
486                 break;
487 #endif
488         }
489 }
490
491 #ifndef FREEBSD
492 enum subcall_style { shift_style, deref_style, mask_style, door_style };
493 #else /* FREEBSD */
494 enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
495
496 struct subcall {
497   int call;
498   int nsubcalls;
499   int subcalls[5];
500 };
501
502 const struct subcall subcalls_table[] = {
503   { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
504 #ifdef SYS_semconfig
505   { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
506 #else
507   { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
508 #endif
509   { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
510 };
511 #endif /* FREEBSD */
512
513 #if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) ))
514
515 const int socket_map [] = {
516                /* SYS_SOCKET      */ 97,
517                /* SYS_BIND        */ 104,
518                /* SYS_CONNECT     */ 98,
519                /* SYS_LISTEN      */ 106,
520                /* SYS_ACCEPT      */ 99,
521                /* SYS_GETSOCKNAME */ 150,
522                /* SYS_GETPEERNAME */ 141,
523                /* SYS_SOCKETPAIR  */ 135,
524                /* SYS_SEND        */ 101,
525                /* SYS_RECV        */ 102,
526                /* SYS_SENDTO      */ 133,
527                /* SYS_RECVFROM    */ 125,
528                /* SYS_SHUTDOWN    */ 134,
529                /* SYS_SETSOCKOPT  */ 105,
530                /* SYS_GETSOCKOPT  */ 118,
531                /* SYS_SENDMSG     */ 114,
532                /* SYS_RECVMSG     */ 113
533 };
534
535 void
536 sparc_socket_decode (tcp)
537 struct tcb *tcp;
538 {
539         volatile long addr;
540         volatile int i, n;
541
542         if (tcp->u_arg [0] < 1 || tcp->u_arg [0] > sizeof(socket_map)/sizeof(int)+1){
543                 return;
544         }
545         tcp->scno = socket_map [tcp->u_arg [0]-1];
546         n = tcp->u_nargs = sysent [tcp->scno].nargs;
547         addr = tcp->u_arg [1];
548         for (i = 0; i < n; i++){
549                 int arg;
550                 if (umoven (tcp, addr, sizeof (arg), (void *) &arg) < 0)
551                         arg = 0;
552                 tcp->u_arg [i] = arg;
553                 addr += sizeof (arg);
554         }
555 }
556
557 void
558 decode_subcall(tcp, subcall, nsubcalls, style)
559 struct tcb *tcp;
560 int subcall;
561 int nsubcalls;
562 enum subcall_style style;
563 {
564         long addr, mask, arg;
565         int i;
566
567         switch (style) {
568         case shift_style:
569                 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
570                         return;
571                 tcp->scno = subcall + tcp->u_arg[0];
572                 if (sysent[tcp->scno].nargs != -1)
573                         tcp->u_nargs = sysent[tcp->scno].nargs;
574                 else
575                         tcp->u_nargs--;
576                 for (i = 0; i < tcp->u_nargs; i++)
577                         tcp->u_arg[i] = tcp->u_arg[i + 1];
578                 break;
579         case deref_style:
580                 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
581                         return;
582                 tcp->scno = subcall + tcp->u_arg[0];
583                 addr = tcp->u_arg[1];
584                 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
585                         if (umove(tcp, addr, &arg) < 0)
586                                 arg = 0;
587                         tcp->u_arg[i] = arg;
588                         addr += sizeof(arg);
589                 }
590                 tcp->u_nargs = sysent[tcp->scno].nargs;
591                 break;
592         case mask_style:
593                 mask = (tcp->u_arg[0] >> 8) & 0xff;
594                 for (i = 0; mask; i++)
595                         mask >>= 1;
596                 if (i >= nsubcalls)
597                         return;
598                 tcp->u_arg[0] &= 0xff;
599                 tcp->scno = subcall + i;
600                 if (sysent[tcp->scno].nargs != -1)
601                         tcp->u_nargs = sysent[tcp->scno].nargs;
602                 break;
603         case door_style:
604                 /*
605                  * Oh, yuck.  The call code is the *sixth* argument.
606                  * (don't you mean the *last* argument? - JH)
607                  */
608                 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
609                         return;
610                 tcp->scno = subcall + tcp->u_arg[5];
611                 if (sysent[tcp->scno].nargs != -1)
612                         tcp->u_nargs = sysent[tcp->scno].nargs;
613                 else
614                         tcp->u_nargs--;
615                 break;
616 #ifdef FREEBSD
617         case table_style:
618                 for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
619                         if (subcalls_table[i].call == tcp->scno) break;
620                 if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
621                     tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
622                         tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
623                         for (i = 0; i < tcp->u_nargs; i++)
624                                 tcp->u_arg[i] = tcp->u_arg[i + 1];
625                 }
626                 break;
627 #endif /* FREEBSD */
628         }
629 }
630 #endif
631
632 struct tcb *tcp_last = NULL;
633
634 static int
635 internal_syscall(tcp)
636 struct tcb *tcp;
637 {
638         /*
639          * We must always trace a few critical system calls in order to
640          * correctly support following forks in the presence of tracing
641          * qualifiers.
642          */
643         switch (tcp->scno + NR_SYSCALL_BASE) {
644 #ifdef SYS_fork
645         case SYS_fork:
646 #endif
647 #ifdef SYS_vfork
648         case SYS_vfork:
649 #endif
650 #ifdef SYS_fork1
651         case SYS_fork1:
652 #endif
653 #ifdef SYS_forkall
654         case SYS_forkall:
655 #endif
656 #ifdef SYS_rfork1
657         case SYS_rfork1:
658 #endif
659 #ifdef SYS_rforkall
660         case SYS_rforkall:
661 #endif
662 #ifdef SYS_rfork
663         case SYS_rfork:
664 #endif
665                 internal_fork(tcp);
666                 break;
667 #ifdef SYS_clone
668         case SYS_clone:
669                 internal_clone(tcp);
670                 break;
671 #endif
672 #ifdef SYS_clone2
673         case SYS_clone2:
674                 internal_clone(tcp);
675                 break;
676 #endif
677 #ifdef SYS_execv
678         case SYS_execv:
679 #endif
680 #ifdef SYS_execve
681         case SYS_execve:
682 #endif
683 #ifdef SYS_rexecve
684         case SYS_rexecve:
685 #endif
686                 internal_exec(tcp);
687                 break;
688
689 #ifdef SYS_wait
690         case SYS_wait:
691 #endif
692 #ifdef SYS_wait4
693         case SYS_wait4:
694 #endif
695 #ifdef SYS32_wait4
696         case SYS32_wait4:
697 #endif
698 #ifdef SYS_waitpid
699         case SYS_waitpid:
700 #endif
701 #ifdef SYS_waitsys
702         case SYS_waitsys:
703 #endif
704                 internal_wait(tcp, 2);
705                 break;
706 #ifdef SYS_waitid
707         case SYS_waitid:
708                 internal_wait(tcp, 3);
709                 break;
710 #endif
711
712 #ifdef SYS_exit
713         case SYS_exit:
714 #endif
715 #ifdef SYS32_exit
716         case SYS32_exit:
717 #endif
718 #ifdef __NR_exit_group
719         case __NR_exit_group:
720 #endif
721 #ifdef IA64
722         case 252: /* IA-32 __NR_exit_group */
723 #endif
724                 internal_exit(tcp);
725                 break;
726         }
727         return 0;
728 }
729
730
731 #ifdef LINUX
732 #if defined (I386)
733         static long eax;
734 #elif defined (IA64)
735         long r8, r10, psr;
736         long ia32 = 0;
737 #elif defined (POWERPC)
738         static long result,flags;
739 #elif defined (M68K)
740         static int d0;
741 #elif defined (ARM)
742         static struct pt_regs regs;
743 #elif defined (ALPHA)
744         static long r0;
745         static long a3;
746 #elif defined (SPARC) || defined (SPARC64)
747         static struct regs regs;
748         static unsigned long trap;
749 #elif defined(MIPS)
750         static long a3;
751         static long r2;
752 #elif defined(S390) || defined(S390X)
753         static long gpr2;
754         static long pc;
755         static long syscall_mode;
756 #elif defined(HPPA)
757         static long r28;
758 #elif defined(SH)
759        static long r0;
760 #elif defined(SH64)
761        static long r9;
762 #elif defined(X86_64)
763        static long rax;
764 #endif
765 #endif /* LINUX */
766 #ifdef FREEBSD
767         struct reg regs;
768 #endif /* FREEBSD */
769
770 int
771 get_scno(tcp)
772 struct tcb *tcp;
773 {
774         long scno = 0;
775 #ifndef USE_PROCFS
776         int pid = tcp->pid;
777 #endif /* !PROCFS */
778
779 #ifdef LINUX
780 #if defined(S390) || defined(S390X)
781         if (tcp->flags & TCB_WAITEXECVE) {
782                 /*
783                  * When the execve system call completes successfully, the
784                  * new process still has -ENOSYS (old style) or __NR_execve
785                  * (new style) in gpr2.  We cannot recover the scno again
786                  * by disassembly, because the image that executed the
787                  * syscall is gone now.  Fortunately, we don't want it.  We
788                  * leave the flag set so that syscall_fixup can fake the
789                  * result.
790                  */
791                 if (tcp->flags & TCB_INSYSCALL)
792                         return 1;
793                 /*
794                  * This is the SIGTRAP after execve.  We cannot try to read
795                  * the system call here either.
796                  */
797                 tcp->flags &= ~TCB_WAITEXECVE;
798                 return 0;
799         }
800
801         if (upeek(pid, PT_GPR2, &syscall_mode) < 0)
802                         return -1;
803
804         if (syscall_mode != -ENOSYS) {
805                 /*
806                  * Since kernel version 2.5.44 the scno gets passed in gpr2.
807                  */
808                 scno = syscall_mode;
809         } else {
810                 /*
811                  * Old style of "passing" the scno via the SVC instruction.
812                  */
813
814                 long opcode, offset_reg, tmp;
815                 void * svc_addr;
816                 int gpr_offset[16] = {PT_GPR0,  PT_GPR1,  PT_ORIGGPR2, PT_GPR3,
817                                       PT_GPR4,  PT_GPR5,  PT_GPR6,     PT_GPR7,
818                                       PT_GPR8,  PT_GPR9,  PT_GPR10,    PT_GPR11,
819                                       PT_GPR12, PT_GPR13, PT_GPR14,    PT_GPR15};
820
821                 if (upeek(pid, PT_PSWADDR, &pc) < 0)
822                         return -1;
823                 errno = 0;
824                 opcode = ptrace(PTRACE_PEEKTEXT, pid, (char *)(pc-sizeof(long)), 0);
825                 if (errno) {
826                         perror("peektext(pc-oneword)");
827                         return -1;
828                 }
829
830                 /*
831                  *  We have to check if the SVC got executed directly or via an
832                  *  EXECUTE instruction. In case of EXECUTE it is necessary to do
833                  *  instruction decoding to derive the system call number.
834                  *  Unfortunately the opcode sizes of EXECUTE and SVC are differently,
835                  *  so that this doesn't work if a SVC opcode is part of an EXECUTE
836                  *  opcode. Since there is no way to find out the opcode size this
837                  *  is the best we can do...
838                  */
839
840                 if ((opcode & 0xff00) == 0x0a00) {
841                         /* SVC opcode */
842                         scno = opcode & 0xff;
843                 }
844                 else {
845                         /* SVC got executed by EXECUTE instruction */
846
847                         /*
848                          *  Do instruction decoding of EXECUTE. If you really want to
849                          *  understand this, read the Principles of Operations.
850                          */
851                         svc_addr = (void *) (opcode & 0xfff);
852
853                         tmp = 0;
854                         offset_reg = (opcode & 0x000f0000) >> 16;
855                         if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
856                                 return -1;
857                         svc_addr += tmp;
858
859                         tmp = 0;
860                         offset_reg = (opcode & 0x0000f000) >> 12;
861                         if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
862                                 return -1;
863                         svc_addr += tmp;
864
865                         scno = ptrace(PTRACE_PEEKTEXT, pid, svc_addr, 0);
866                         if (errno)
867                                 return -1;
868 #if defined(S390X)
869                         scno >>= 48;
870 #else
871                         scno >>= 16;
872 #endif
873                         tmp = 0;
874                         offset_reg = (opcode & 0x00f00000) >> 20;
875                         if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
876                                 return -1;
877
878                         scno = (scno | tmp) & 0xff;
879                 }
880         }
881 #elif defined (POWERPC)
882         if (upeek(pid, sizeof(unsigned long)*PT_R0, &scno) < 0)
883                 return -1;
884         if (!(tcp->flags & TCB_INSYSCALL)) {
885                 /* Check if we return from execve. */
886                 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
887                         tcp->flags &= ~TCB_WAITEXECVE;
888                         return 0;
889                 }
890         }
891 #elif defined (I386)
892         if (upeek(pid, 4*ORIG_EAX, &scno) < 0)
893                 return -1;
894 #elif defined (X86_64)
895         if (upeek(pid, 8*ORIG_RAX, &scno) < 0)
896                 return -1;
897
898         if (!(tcp->flags & TCB_INSYSCALL)) {
899                 static int currpers=-1;
900                 long val;
901
902                 /* Check CS register value. On x86-64 linux it is:
903                  *      0x33    for long mode (64 bit)
904                  *      0x23    for compatibility mode (32 bit)
905                  * It takes only one ptrace and thus doesn't need
906                  * to be cached.
907                  */
908                 if (upeek(pid, 8*CS, &val) < 0)
909                         return -1;
910                 switch(val)
911                 {
912                         case 0x23: currpers = 1; break;
913                         case 0x33: currpers = 0; break;
914                         default:
915                                 fprintf(stderr, "Unknown value CS=0x%02X while "
916                                          "detecting personality of process "
917                                          "PID=%d\n", (int)val, pid);
918                                 currpers = current_personality;
919                                 break;
920                 }
921 #if 0
922                 /* This version analyzes the opcode of a syscall instruction.
923                  * (int 0x80 on i386 vs. syscall on x86-64)
924                  * It works, but is too complicated.
925                  */
926                 unsigned long val, rip, i;
927
928                 if(upeek(pid, 8*RIP, &rip)<0)
929                         perror("upeek(RIP)");
930
931                 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
932                 rip-=2;
933                 errno = 0;
934
935                 call = ptrace(PTRACE_PEEKTEXT,pid,(char *)rip,0);
936                 if (errno)
937                         printf("ptrace_peektext failed: %s\n",
938                                         strerror(errno));
939                 switch (call & 0xffff)
940                 {
941                         /* x86-64: syscall = 0x0f 0x05 */
942                         case 0x050f: currpers = 0; break;
943                         /* i386: int 0x80 = 0xcd 0x80 */
944                         case 0x80cd: currpers = 1; break;
945                         default:
946                                 currpers = current_personality;
947                                 fprintf(stderr,
948                                         "Unknown syscall opcode (0x%04X) while "
949                                         "detecting personality of process "
950                                         "PID=%d\n", (int)call, pid);
951                                 break;
952                 }
953 #endif
954                 if(currpers != current_personality)
955                 {
956                         char *names[]={"64 bit", "32 bit"};
957                         set_personality(currpers);
958                         printf("[ Process PID=%d runs in %s mode. ]\n",
959                                         pid, names[current_personality]);
960                 }
961         }
962 #elif defined(IA64)
963 #       define IA64_PSR_IS      ((long)1 << 34)
964         if (upeek (pid, PT_CR_IPSR, &psr) >= 0)
965                 ia32 = (psr & IA64_PSR_IS) != 0;
966         if (!(tcp->flags & TCB_INSYSCALL)) {
967                 if (ia32) {
968                         if (upeek(pid, PT_R1, &scno) < 0)       /* orig eax */
969                                 return -1;
970                 } else {
971                         if (upeek (pid, PT_R15, &scno) < 0)
972                                 return -1;
973                 }
974                 /* Check if we return from execve. */
975                 if (tcp->flags & TCB_WAITEXECVE) {
976                         tcp->flags &= ~TCB_WAITEXECVE;
977                         return 0;
978                 }
979         } else {
980                 /* syscall in progress */
981                 if (upeek (pid, PT_R8, &r8) < 0)
982                         return -1;
983                 if (upeek (pid, PT_R10, &r10) < 0)
984                         return -1;
985         }
986 #elif defined (ARM)
987         /*
988          * Read complete register set in one go.
989          */
990         if (ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs) == -1)
991                 return -1;
992
993         /*
994          * We only need to grab the syscall number on syscall entry.
995          */
996         if (regs.ARM_ip == 0) {
997                 /*
998                  * Note: we only deal with only 32-bit CPUs here.
999                  */
1000                 if (regs.ARM_cpsr & 0x20) {
1001                         /*
1002                          * Get the Thumb-mode system call number
1003                          */
1004                         scno = regs.ARM_r7;
1005                 } else {
1006                         /*
1007                          * Get the ARM-mode system call number
1008                          */
1009                         errno = 0;
1010                         scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
1011                         if (errno)
1012                                 return -1;
1013
1014                         if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1015                                 tcp->flags &= ~TCB_WAITEXECVE;
1016                                 return 0;
1017                         }
1018
1019                         if ((scno & 0x0ff00000) != 0x0f900000) {
1020                                 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1021                                         scno);
1022                                 return -1;
1023                         }
1024
1025                         /*
1026                          * Fixup the syscall number
1027                          */
1028                         scno &= 0x000fffff;
1029                 }
1030
1031                 if (tcp->flags & TCB_INSYSCALL) {
1032                         fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1033                         tcp->flags &= ~TCB_INSYSCALL;
1034                 }
1035         } else {
1036                 if (!(tcp->flags & TCB_INSYSCALL)) {
1037                         fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1038                         tcp->flags |= TCB_INSYSCALL;
1039                 }
1040         }
1041 #elif defined (M68K)
1042         if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
1043                 return -1;
1044 #elif defined (MIPS)
1045         if (upeek(pid, REG_A3, &a3) < 0)
1046                 return -1;
1047
1048         if(!(tcp->flags & TCB_INSYSCALL)) {
1049                 if (upeek(pid, REG_V0, &scno) < 0)
1050                         return -1;
1051
1052                 if (scno < 0 || scno > nsyscalls) {
1053                         if(a3 == 0 || a3 == -1) {
1054                                 if(debug)
1055                                         fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1056                                 return 0;
1057                         }
1058                 }
1059         } else {
1060                 if (upeek(pid, REG_V0, &r2) < 0)
1061                         return -1;
1062         }
1063 #elif defined (ALPHA)
1064         if (upeek(pid, REG_A3, &a3) < 0)
1065                 return -1;
1066
1067         if (!(tcp->flags & TCB_INSYSCALL)) {
1068                 if (upeek(pid, REG_R0, &scno) < 0)
1069                         return -1;
1070
1071                 /* Check if we return from execve. */
1072                 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1073                         tcp->flags &= ~TCB_WAITEXECVE;
1074                         return 0;
1075                 }
1076
1077                 /*
1078                  * Do some sanity checks to figure out if it's
1079                  * really a syscall entry
1080                  */
1081                 if (scno < 0 || scno > nsyscalls) {
1082                         if (a3 == 0 || a3 == -1) {
1083                                 if (debug)
1084                                         fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1085                                 return 0;
1086                         }
1087                 }
1088         }
1089         else {
1090                 if (upeek(pid, REG_R0, &r0) < 0)
1091                         return -1;
1092         }
1093 #elif defined (SPARC) || defined (SPARC64)
1094         /* Everything we need is in the current register set. */
1095         if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
1096                 return -1;
1097
1098         /* If we are entering, then disassemble the syscall trap. */
1099         if (!(tcp->flags & TCB_INSYSCALL)) {
1100                 /* Retrieve the syscall trap instruction. */
1101                 errno = 0;
1102                 trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
1103 #if defined(SPARC64)
1104                 trap >>= 32;
1105 #endif
1106                 if (errno)
1107                         return -1;
1108
1109                 /* Disassemble the trap to see what personality to use. */
1110                 switch (trap) {
1111                 case 0x91d02010:
1112                         /* Linux/SPARC syscall trap. */
1113                         set_personality(0);
1114                         break;
1115                 case 0x91d0206d:
1116                         /* Linux/SPARC64 syscall trap. */
1117                         set_personality(2);
1118                         break;
1119                 case 0x91d02000:
1120                         /* SunOS syscall trap. (pers 1) */
1121                         fprintf(stderr,"syscall: SunOS no support\n");
1122                         return -1;
1123                 case 0x91d02008:
1124                         /* Solaris 2.x syscall trap. (per 2) */
1125                         set_personality(1);
1126                         break;
1127                 case 0x91d02009:
1128                         /* NetBSD/FreeBSD syscall trap. */
1129                         fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1130                         return -1;
1131                 case 0x91d02027:
1132                         /* Solaris 2.x gettimeofday */
1133                         set_personality(1);
1134                         break;
1135                 default:
1136                         /* Unknown syscall trap. */
1137                         if(tcp->flags & TCB_WAITEXECVE) {
1138                                 tcp->flags &= ~TCB_WAITEXECVE;
1139                                 return 0;
1140                         }
1141 #if defined (SPARC64)
1142                         fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc);
1143 #else
1144                         fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
1145 #endif
1146                         return -1;
1147                 }
1148
1149                 /* Extract the system call number from the registers. */
1150                 if (trap == 0x91d02027)
1151                         scno = 156;
1152                 else
1153                         scno = regs.r_g1;
1154                 if (scno == 0) {
1155                         scno = regs.r_o0;
1156                         memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
1157                 }
1158         }
1159 #elif defined(HPPA)
1160         if (upeek(pid, PT_GR20, &scno) < 0)
1161                 return -1;
1162         if (!(tcp->flags & TCB_INSYSCALL)) {
1163                 /* Check if we return from execve. */
1164                 if ((tcp->flags & TCB_WAITEXECVE)) {
1165                         tcp->flags &= ~TCB_WAITEXECVE;
1166                         return 0;
1167                 }
1168         }
1169 #elif defined(SH)
1170        /*
1171         * In the new syscall ABI, the system call number is in R3.
1172         */
1173        if (upeek(pid, 4*(REG_REG0+3), &scno) < 0)
1174                return -1;
1175
1176        if (scno < 0) {
1177            /* Odd as it may seem, a glibc bug has been known to cause
1178               glibc to issue bogus negative syscall numbers.  So for
1179               our purposes, make strace print what it *should* have been */
1180            long correct_scno = (scno & 0xff);
1181            if (debug)
1182                fprintf(stderr,
1183                    "Detected glibc bug: bogus system call number = %ld, "
1184                    "correcting to %ld\n",
1185                    scno,
1186                    correct_scno);
1187            scno = correct_scno;
1188        }
1189
1190
1191        if (!(tcp->flags & TCB_INSYSCALL)) {
1192                /* Check if we return from execve. */
1193                if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1194                        tcp->flags &= ~TCB_WAITEXECVE;
1195                        return 0;
1196                }
1197        }
1198 #elif defined(SH64)
1199         if (upeek(pid, REG_SYSCALL, &scno) < 0)
1200                 return -1;
1201         scno &= 0xFFFF;
1202
1203         if (!(tcp->flags & TCB_INSYSCALL)) {
1204                 /* Check if we return from execve. */
1205                 if (tcp->flags & TCB_WAITEXECVE) {
1206                         tcp->flags &= ~TCB_WAITEXECVE;
1207                         return 0;
1208                 }
1209         }
1210 #endif /* SH64 */
1211 #endif /* LINUX */
1212 #ifdef SUNOS4
1213         if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
1214                 return -1;
1215 #elif defined(SH)
1216         /* new syscall ABI returns result in R0 */
1217         if (upeek(pid, 4*REG_REG0, (long *)&r0) < 0)
1218                 return -1;
1219 #elif defined(SH64)
1220         /* ABI defines result returned in r9 */
1221         if (upeek(pid, REG_GENERAL(9), (long *)&r9) < 0)
1222                 return -1;
1223
1224 #endif
1225 #ifdef USE_PROCFS
1226 #ifdef HAVE_PR_SYSCALL
1227         scno = tcp->status.PR_SYSCALL;
1228 #else /* !HAVE_PR_SYSCALL */
1229 #ifndef FREEBSD
1230         scno = tcp->status.PR_WHAT;
1231 #else /* FREEBSD */
1232         if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1233                 perror("pread");
1234                 return -1;
1235         }
1236         switch (regs.r_eax) {
1237         case SYS_syscall:
1238         case SYS___syscall:
1239                 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1240                 break;
1241         default:
1242                 scno = regs.r_eax;
1243                 break;
1244         }
1245 #endif /* FREEBSD */
1246 #endif /* !HAVE_PR_SYSCALL */
1247 #endif /* USE_PROCFS */
1248         if (!(tcp->flags & TCB_INSYSCALL))
1249                 tcp->scno = scno;
1250         return 1;
1251 }
1252
1253
1254 int
1255 syscall_fixup(tcp)
1256 struct tcb *tcp;
1257 {
1258 #ifndef USE_PROCFS
1259         int pid = tcp->pid;
1260 #else /* USE_PROCFS */
1261         int scno = tcp->scno;
1262
1263         if (!(tcp->flags & TCB_INSYSCALL)) {
1264                 if (tcp->status.PR_WHY != PR_SYSENTRY) {
1265                         if (
1266                             scno == SYS_fork
1267 #ifdef SYS_vfork
1268                             || scno == SYS_vfork
1269 #endif /* SYS_vfork */
1270 #ifdef SYS_fork1
1271                             || scno == SYS_fork1
1272 #endif /* SYS_fork1 */
1273 #ifdef SYS_forkall
1274                             || scno == SYS_forkall
1275 #endif /* SYS_forkall */
1276 #ifdef SYS_rfork1
1277                             || scno == SYS_rfork1
1278 #endif /* SYS_fork1 */
1279 #ifdef SYS_rforkall
1280                             || scno == SYS_rforkall
1281 #endif /* SYS_rforkall */
1282                             ) {
1283                                 /* We are returning in the child, fake it. */
1284                                 tcp->status.PR_WHY = PR_SYSENTRY;
1285                                 trace_syscall(tcp);
1286                                 tcp->status.PR_WHY = PR_SYSEXIT;
1287                         }
1288                         else {
1289                                 fprintf(stderr, "syscall: missing entry\n");
1290                                 tcp->flags |= TCB_INSYSCALL;
1291                         }
1292                 }
1293         }
1294         else {
1295                 if (tcp->status.PR_WHY != PR_SYSEXIT) {
1296                         fprintf(stderr, "syscall: missing exit\n");
1297                         tcp->flags &= ~TCB_INSYSCALL;
1298                 }
1299         }
1300 #endif /* USE_PROCFS */
1301 #ifdef SUNOS4
1302         if (!(tcp->flags & TCB_INSYSCALL)) {
1303                 if (scno == 0) {
1304                         fprintf(stderr, "syscall: missing entry\n");
1305                         tcp->flags |= TCB_INSYSCALL;
1306                 }
1307         }
1308         else {
1309                 if (scno != 0) {
1310                         if (debug) {
1311                                 /*
1312                                  * This happens when a signal handler
1313                                  * for a signal which interrupted a
1314                                  * a system call makes another system call.
1315                                  */
1316                                 fprintf(stderr, "syscall: missing exit\n");
1317                         }
1318                         tcp->flags &= ~TCB_INSYSCALL;
1319                 }
1320         }
1321 #endif /* SUNOS4 */
1322 #ifdef LINUX
1323 #if defined (I386)
1324         if (upeek(pid, 4*EAX, &eax) < 0)
1325                 return -1;
1326         if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1327                 if (debug)
1328                         fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1329                 return 0;
1330         }
1331 #elif defined (X86_64)
1332         if (upeek(pid, 8*RAX, &rax) < 0)
1333                 return -1;
1334         if (current_personality == 1)
1335                 rax = (long int)(int)rax; /* sign extend from 32 bits */
1336         if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1337                 if (debug)
1338                         fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1339                 return 0;
1340         }
1341 #elif defined (S390) || defined (S390X)
1342         if (upeek(pid, PT_GPR2, &gpr2) < 0)
1343                 return -1;
1344         if (syscall_mode != -ENOSYS)
1345                 syscall_mode = tcp->scno;
1346         if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
1347                 if (debug)
1348                         fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1349                 return 0;
1350         }
1351         else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1352                   == (TCB_INSYSCALL|TCB_WAITEXECVE))
1353                  && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1354                 /*
1355                  * Fake a return value of zero.  We leave the TCB_WAITEXECVE
1356                  * flag set for the post-execve SIGTRAP to see and reset.
1357                  */
1358                 gpr2 = 0;
1359         }
1360 #elif defined (POWERPC)
1361 # define SO_MASK 0x10000000
1362         if (upeek(pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1363                 return -1;
1364         if (upeek(pid, sizeof(unsigned long)*PT_R3, &result) < 0)
1365                 return -1;
1366         if (flags & SO_MASK)
1367                 result = -result;
1368 #elif defined (M68K)
1369         if (upeek(pid, 4*PT_D0, &d0) < 0)
1370                 return -1;
1371         if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1372                 if (debug)
1373                         fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1374                 return 0;
1375         }
1376 #elif defined (ARM)
1377         /*
1378          * Nothing required
1379          */
1380 #elif defined (HPPA)
1381         if (upeek(pid, PT_GR28, &r28) < 0)
1382                 return -1;
1383 #elif defined(IA64)
1384         if (upeek(pid, PT_R10, &r10) < 0)
1385                 return -1;
1386         if (upeek(pid, PT_R8, &r8) < 0)
1387                 return -1;
1388         if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1389                 if (debug)
1390                         fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1391                 return 0;
1392         }
1393 #endif
1394 #endif /* LINUX */
1395         return 1;
1396 }
1397
1398 int
1399 get_error(tcp)
1400 struct tcb *tcp;
1401 {
1402         int u_error = 0;
1403 #ifdef LINUX
1404 #if defined(S390) || defined(S390X)
1405                 if (gpr2 && (unsigned) -gpr2 < nerrnos) {
1406                         tcp->u_rval = -1;
1407                         u_error = -gpr2;
1408                 }
1409                 else {
1410                         tcp->u_rval = gpr2;
1411                         u_error = 0;
1412                 }
1413 #else /* !S390 && !S390X */
1414 #ifdef I386
1415                 if (eax < 0 && -eax < nerrnos) {
1416                         tcp->u_rval = -1;
1417                         u_error = -eax;
1418                 }
1419                 else {
1420                         tcp->u_rval = eax;
1421                         u_error = 0;
1422                 }
1423 #else /* !I386 */
1424 #ifdef X86_64
1425                 if (rax < 0 && -rax < nerrnos) {
1426                         tcp->u_rval = -1;
1427                         u_error = -rax;
1428                 }
1429                 else {
1430                         tcp->u_rval = rax;
1431                         u_error = 0;
1432                 }
1433 #else
1434 #ifdef IA64
1435                 if (ia32) {
1436                         int err;
1437
1438                         err = (int)r8;
1439                         if (err < 0 && -err < nerrnos) {
1440                                 tcp->u_rval = -1;
1441                                 u_error = -err;
1442                         }
1443                         else {
1444                                 tcp->u_rval = err;
1445                                 u_error = 0;
1446                         }
1447                 } else {
1448                         if (r10) {
1449                                 tcp->u_rval = -1;
1450                                 u_error = r8;
1451                         } else {
1452                                 tcp->u_rval = r8;
1453                                 u_error = 0;
1454                         }
1455                 }
1456 #else /* !IA64 */
1457 #ifdef MIPS
1458                 if (a3) {
1459                         tcp->u_rval = -1;
1460                         u_error = r2;
1461                 } else {
1462                         tcp->u_rval = r2;
1463                         u_error = 0;
1464                 }
1465 #else
1466 #ifdef POWERPC
1467                 if (result && (unsigned long) -result < nerrnos) {
1468                         tcp->u_rval = -1;
1469                         u_error = -result;
1470                 }
1471                 else {
1472                         tcp->u_rval = result;
1473                         u_error = 0;
1474                 }
1475 #else /* !POWERPC */
1476 #ifdef M68K
1477                 if (d0 && (unsigned) -d0 < nerrnos) {
1478                         tcp->u_rval = -1;
1479                         u_error = -d0;
1480                 }
1481                 else {
1482                         tcp->u_rval = d0;
1483                         u_error = 0;
1484                 }
1485 #else /* !M68K */
1486 #ifdef ARM
1487                 if (regs.ARM_r0 && (unsigned) -regs.ARM_r0 < nerrnos) {
1488                         tcp->u_rval = -1;
1489                         u_error = -regs.ARM_r0;
1490                 }
1491                 else {
1492                         tcp->u_rval = regs.ARM_r0;
1493                         u_error = 0;
1494                 }
1495 #else /* !ARM */
1496 #ifdef ALPHA
1497                 if (a3) {
1498                         tcp->u_rval = -1;
1499                         u_error = r0;
1500                 }
1501                 else {
1502                         tcp->u_rval = r0;
1503                         u_error = 0;
1504                 }
1505 #else /* !ALPHA */
1506 #ifdef SPARC
1507                 if (regs.r_psr & PSR_C) {
1508                         tcp->u_rval = -1;
1509                         u_error = regs.r_o0;
1510                 }
1511                 else {
1512                         tcp->u_rval = regs.r_o0;
1513                         u_error = 0;
1514                 }
1515 #else /* !SPARC */
1516 #ifdef SPARC64
1517                 if (regs.r_tstate & 0x1100000000UL) {
1518                         tcp->u_rval = -1;
1519                         u_error = regs.r_o0;
1520                 }
1521                 else {
1522                         tcp->u_rval = regs.r_o0;
1523                         u_error = 0;
1524                 }
1525 #else /* !SPARC64 */
1526 #ifdef HPPA
1527                 if (r28 && (unsigned) -r28 < nerrnos) {
1528                         tcp->u_rval = -1;
1529                         u_error = -r28;
1530                 }
1531                 else {
1532                         tcp->u_rval = r28;
1533                         u_error = 0;
1534                 }
1535 #else
1536 #ifdef SH
1537                /* interpret R0 as return value or error number */
1538                if (r0 && (unsigned) -r0 < nerrnos) {
1539                        tcp->u_rval = -1;
1540                        u_error = -r0;
1541                }
1542                else {
1543                        tcp->u_rval = r0;
1544                        u_error = 0;
1545                }
1546 #else
1547 #ifdef SH64
1548                 /* interpret result as return value or error number */
1549                 if (r9 && (unsigned) -r9 < nerrnos) {
1550                         tcp->u_rval = -1;
1551                         u_error = -r9;
1552                 }
1553                 else {
1554                         tcp->u_rval = r9;
1555                         u_error = 0;
1556                 }
1557 #endif /* SH64 */
1558 #endif /* SH */
1559 #endif /* HPPA */
1560 #endif /* SPARC */
1561 #endif /* SPARC64 */
1562 #endif /* ALPHA */
1563 #endif /* ARM */
1564 #endif /* M68K */
1565 #endif /* POWERPC */
1566 #endif /* MIPS */
1567 #endif /* IA64 */
1568 #endif /* X86_64 */
1569 #endif /* I386 */
1570 #endif /* S390 || S390X */
1571 #endif /* LINUX */
1572 #ifdef SUNOS4
1573                 /* get error code from user struct */
1574                 if (upeek(pid, uoff(u_error), &u_error) < 0)
1575                         return -1;
1576                 u_error >>= 24; /* u_error is a char */
1577
1578                 /* get system call return value */
1579                 if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
1580                         return -1;
1581 #endif /* SUNOS4 */
1582 #ifdef SVR4
1583 #ifdef SPARC
1584                 /* Judicious guessing goes a long way. */
1585                 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1586                         tcp->u_rval = -1;
1587                         u_error = tcp->status.pr_reg[R_O0];
1588                 }
1589                 else {
1590                         tcp->u_rval = tcp->status.pr_reg[R_O0];
1591                         u_error = 0;
1592                 }
1593 #endif /* SPARC */
1594 #ifdef I386
1595                 /* Wanna know how to kill an hour single-stepping? */
1596                 if (tcp->status.PR_REG[EFL] & 0x1) {
1597                         tcp->u_rval = -1;
1598                         u_error = tcp->status.PR_REG[EAX];
1599                 }
1600                 else {
1601                         tcp->u_rval = tcp->status.PR_REG[EAX];
1602 #ifdef HAVE_LONG_LONG
1603                         tcp->u_lrval =
1604                                 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1605                                 tcp->status.PR_REG[EAX];
1606 #endif
1607                         u_error = 0;
1608                 }
1609 #endif /* I386 */
1610 #ifdef X86_64
1611                 /* Wanna know how to kill an hour single-stepping? */
1612                 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1613                         tcp->u_rval = -1;
1614                         u_error = tcp->status.PR_REG[RAX];
1615                 }
1616                 else {
1617                         tcp->u_rval = tcp->status.PR_REG[RAX];
1618                         u_error = 0;
1619                 }
1620 #endif /* X86_64 */
1621 #ifdef MIPS
1622                 if (tcp->status.pr_reg[CTX_A3]) {
1623                         tcp->u_rval = -1;
1624                         u_error = tcp->status.pr_reg[CTX_V0];
1625                 }
1626                 else {
1627                         tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1628                         u_error = 0;
1629                 }
1630 #endif /* MIPS */
1631 #endif /* SVR4 */
1632 #ifdef FREEBSD
1633                 if (regs.r_eflags & PSL_C) {
1634                         tcp->u_rval = -1;
1635                         u_error = regs.r_eax;
1636                 } else {
1637                         tcp->u_rval = regs.r_eax;
1638                         tcp->u_lrval =
1639                           ((unsigned long long) regs.r_edx << 32) +  regs.r_eax;
1640                         u_error = 0;
1641                 }
1642 #endif /* FREEBSD */
1643         tcp->u_error = u_error;
1644         return 1;
1645 }
1646
1647 int
1648 force_result(tcp, error, rval)
1649         struct tcb *tcp;
1650         int error;
1651         long rval;
1652 {
1653 #ifdef LINUX
1654 #if defined(S390) || defined(S390X)
1655         gpr2 = error ? -error : rval;
1656         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1657                 return -1;
1658 #else /* !S390 && !S390X */
1659 #ifdef I386
1660         eax = error ? -error : rval;
1661         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1662                 return -1;
1663 #else /* !I386 */
1664 #ifdef X86_64
1665         rax = error ? -error : rval;
1666         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
1667                 return -1;
1668 #else
1669 #ifdef IA64
1670         if (ia32) {
1671                 r8 = error ? -error : rval;
1672                 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1673                         return -1;
1674         }
1675         else {
1676                 if (error) {
1677                         r8 = error;
1678                         r10 = -1;
1679                 }
1680                 else {
1681                         r8 = rval;
1682                         r10 = 0;
1683                 }
1684                 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1685                     ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1686                         return -1;
1687         }
1688 #else /* !IA64 */
1689 #ifdef MIPS
1690         if (error) {
1691                 r2 = error;
1692                 a3 = -1;
1693         }
1694         else {
1695                 r2 = rval;
1696                 a3 = 0;
1697         }
1698         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1699             ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1700                 return -1;
1701 #else
1702 #ifdef POWERPC
1703         if (upeek(tcp->pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1704                 return -1;
1705         if (error) {
1706                 flags |= SO_MASK;
1707                 result = error;
1708         }
1709         else {
1710                 flags &= ~SO_MASK;
1711                 result = rval;
1712         }
1713         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1714             ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
1715                 return -1;
1716 #else /* !POWERPC */
1717 #ifdef M68K
1718         d0 = error ? -error : rval;
1719         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1720                 return -1;
1721 #else /* !M68K */
1722 #ifdef ARM
1723        regs.ARM_r0 = error ? -error : rval;
1724        if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
1725                 return -1;
1726 #else /* !ARM */
1727 #ifdef ALPHA
1728         if (error) {
1729                 a3 = -1;
1730                 r0 = error;
1731         }
1732         else {
1733                 a3 = 0;
1734                 r0 = rval;
1735         }
1736         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1737             ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1738                 return -1;
1739 #else /* !ALPHA */
1740 #ifdef SPARC
1741         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1742                 return -1;
1743         if (error) {
1744                 regs.r_psr |= PSR_C;
1745                 regs.r_o0 = error;
1746         }
1747         else {
1748                 regs.r_psr &= ~PSR_C;
1749                 regs.r_o0 = rval;
1750         }
1751         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1752                 return -1;
1753 #else /* !SPARC */
1754 #ifdef SPARC64
1755         if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1756                 return -1;
1757         if (error) {
1758                 regs.r_tstate |= 0x1100000000UL;
1759                 regs.r_o0 = error;
1760         }
1761         else {
1762                 regs.r_tstate &= ~0x1100000000UL;
1763                 regs.r_o0 = rval;
1764         }
1765         if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1766                 return -1;
1767 #else /* !SPARC64 */
1768 #ifdef HPPA
1769         r28 = error ? -error : rval;
1770         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1771                 return -1;
1772 #else
1773 #ifdef SH
1774         r0 = error ? -error : rval;
1775         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1776                 return -1;
1777 #else
1778 #ifdef SH64
1779         r9 = error ? -error : rval;
1780         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1781                 return -1;
1782 #endif /* SH64 */
1783 #endif /* SH */
1784 #endif /* HPPA */
1785 #endif /* SPARC */
1786 #endif /* SPARC64 */
1787 #endif /* ALPHA */
1788 #endif /* ARM */
1789 #endif /* M68K */
1790 #endif /* POWERPC */
1791 #endif /* MIPS */
1792 #endif /* IA64 */
1793 #endif /* X86_64 */
1794 #endif /* I386 */
1795 #endif /* S390 || S390X */
1796 #endif /* LINUX */
1797 #ifdef SUNOS4
1798         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1799                    error << 24) < 0 ||
1800             ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1801                 return -1;
1802 #endif /* SUNOS4 */
1803 #ifdef SVR4
1804         /* XXX no clue */
1805         return -1;
1806 #endif /* SVR4 */
1807 #ifdef FREEBSD
1808         if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1809                 perror("pread");
1810                 return -1;
1811         }
1812         if (error) {
1813                 regs.r_eflags |= PSL_C;
1814                 regs.r_eax = error;
1815         }
1816         else {
1817                 regs.r_eflags &= ~PSL_C;
1818                 regs.r_eax = rval;
1819         }
1820         if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1821                 perror("pwrite");
1822                 return -1;
1823         }
1824 #endif /* FREEBSD */
1825
1826         /* All branches reach here on success (only).  */
1827         tcp->u_error = error;
1828         tcp->u_rval = rval;
1829         return 0;
1830 }
1831
1832 int syscall_enter(tcp)
1833 struct tcb *tcp;
1834 {
1835 #ifndef USE_PROCFS
1836         int pid = tcp->pid;
1837 #endif /* !USE_PROCFS */
1838 #ifdef LINUX
1839 #if defined(S390) || defined(S390X)
1840         {
1841                 int i;
1842                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1843                         tcp->u_nargs = sysent[tcp->scno].nargs;
1844                 else
1845                         tcp->u_nargs = MAX_ARGS;
1846                 for (i = 0; i < tcp->u_nargs; i++) {
1847                         if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
1848                                 return -1;
1849                 }
1850         }
1851 #elif defined (ALPHA)
1852         {
1853                 int i;
1854                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1855                         tcp->u_nargs = sysent[tcp->scno].nargs;
1856                 else
1857                         tcp->u_nargs = MAX_ARGS;
1858                 for (i = 0; i < tcp->u_nargs; i++) {
1859                         /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1860                          * for scno somewhere above here!
1861                          */
1862                         if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1863                                 return -1;
1864                 }
1865         }
1866 #elif defined (IA64)
1867         {
1868                 if (!ia32) {
1869                         unsigned long *out0, *rbs_end, cfm, sof, sol, i;
1870                         /* be backwards compatible with kernel < 2.4.4... */
1871 #                       ifndef PT_RBS_END
1872 #                         define PT_RBS_END     PT_AR_BSP
1873 #                       endif
1874
1875                         if (upeek(pid, PT_RBS_END, (long *) &rbs_end) < 0)
1876                                 return -1;
1877                         if (upeek(pid, PT_CFM, (long *) &cfm) < 0)
1878                                 return -1;
1879
1880                         sof = (cfm >> 0) & 0x7f;
1881                         sol = (cfm >> 7) & 0x7f;
1882                         out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
1883
1884                         if (tcp->scno >= 0 && tcp->scno < nsyscalls
1885                             && sysent[tcp->scno].nargs != -1)
1886                                 tcp->u_nargs = sysent[tcp->scno].nargs;
1887                         else
1888                                 tcp->u_nargs = MAX_ARGS;
1889                         for (i = 0; i < tcp->u_nargs; ++i) {
1890                                 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1891                                            sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1892                                         return -1;
1893                         }
1894                 } else {
1895                         int i;
1896
1897                         if (/* EBX = out0 */
1898                             upeek(pid, PT_R11, (long *) &tcp->u_arg[0]) < 0
1899                             /* ECX = out1 */
1900                             || upeek(pid, PT_R9,  (long *) &tcp->u_arg[1]) < 0
1901                             /* EDX = out2 */
1902                             || upeek(pid, PT_R10, (long *) &tcp->u_arg[2]) < 0
1903                             /* ESI = out3 */
1904                             || upeek(pid, PT_R14, (long *) &tcp->u_arg[3]) < 0
1905                             /* EDI = out4 */
1906                             || upeek(pid, PT_R15, (long *) &tcp->u_arg[4]) < 0
1907                             /* EBP = out5 */
1908                             || upeek(pid, PT_R13, (long *) &tcp->u_arg[5]) < 0)
1909                                 return -1;
1910
1911                         for (i = 0; i < 6; ++i)
1912                                 /* truncate away IVE sign-extension */
1913                                 tcp->u_arg[i] &= 0xffffffff;
1914
1915                         if (tcp->scno >= 0 && tcp->scno < nsyscalls
1916                             && sysent[tcp->scno].nargs != -1)
1917                                 tcp->u_nargs = sysent[tcp->scno].nargs;
1918                         else
1919                                 tcp->u_nargs = 5;
1920                 }
1921         }
1922 #elif defined (MIPS)
1923         {
1924                 long sp;
1925                 int i, nargs;
1926
1927                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1928                         nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
1929                 else
1930                         nargs = tcp->u_nargs = MAX_ARGS;
1931                 if(nargs > 4) {
1932                         if(upeek(pid, REG_SP, &sp) < 0)
1933                                 return -1;
1934                         for(i = 0; i < 4; i++) {
1935                                 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
1936                                         return -1;
1937                         }
1938                         umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
1939                                (char *)(tcp->u_arg + 4));
1940                 } else {
1941                         for(i = 0; i < nargs; i++) {
1942                                 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
1943                                         return -1;
1944                         }
1945                 }
1946         }
1947 #elif defined (POWERPC)
1948 #ifndef PT_ORIG_R3
1949 #define PT_ORIG_R3 34
1950 #endif
1951         {
1952                 int i;
1953                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1954                         tcp->u_nargs = sysent[tcp->scno].nargs;
1955                 else
1956                         tcp->u_nargs = MAX_ARGS;
1957                 for (i = 0; i < tcp->u_nargs; i++) {
1958                         if (upeek(pid, (i==0) ?
1959                                 (sizeof(unsigned long)*PT_ORIG_R3) :
1960                                 ((i+PT_R3)*sizeof(unsigned long)),
1961                                         &tcp->u_arg[i]) < 0)
1962                                 return -1;
1963                 }
1964         }
1965 #elif defined (SPARC) || defined (SPARC64)
1966         {
1967                 int i;
1968
1969                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1970                         tcp->u_nargs = sysent[tcp->scno].nargs;
1971                 else
1972                         tcp->u_nargs = MAX_ARGS;
1973                 for (i = 0; i < tcp->u_nargs; i++)
1974                         tcp->u_arg[i] = *((&regs.r_o0) + i);
1975         }
1976 #elif defined (HPPA)
1977         {
1978                 int i;
1979
1980                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1981                         tcp->u_nargs = sysent[tcp->scno].nargs;
1982                 else
1983                         tcp->u_nargs = MAX_ARGS;
1984                 for (i = 0; i < tcp->u_nargs; i++) {
1985                         if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1986                                 return -1;
1987                 }
1988         }
1989 #elif defined(ARM)
1990         {
1991                 int i;
1992
1993                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1994                         tcp->u_nargs = sysent[tcp->scno].nargs;
1995                 else
1996                         tcp->u_nargs = MAX_ARGS;
1997                 for (i = 0; i < tcp->u_nargs; i++)
1998                         tcp->u_arg[i] = regs.uregs[i];
1999         }
2000 #elif defined(SH)
2001        {
2002                int i;
2003                static int syscall_regs[] = {
2004                    REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2005                    REG_REG0, REG_REG0+1, REG_REG0+2
2006                    };
2007
2008                tcp->u_nargs = sysent[tcp->scno].nargs;
2009                for (i = 0; i < tcp->u_nargs; i++) {
2010                        if (upeek(pid, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2011                                return -1;
2012                }
2013         }
2014 #elif defined(SH64)
2015         {
2016                 int i;
2017                 /* Registers used by SH5 Linux system calls for parameters */
2018                 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2019
2020                 /*
2021                  * TODO: should also check that the number of arguments encoded
2022                  *       in the trap number matches the number strace expects.
2023                  */
2024                 /*
2025                     assert(sysent[tcp->scno].nargs <
2026                         sizeof(syscall_regs)/sizeof(syscall_regs[0]));
2027                  */
2028
2029                 tcp->u_nargs = sysent[tcp->scno].nargs;
2030                 for (i = 0; i < tcp->u_nargs; i++) {
2031                         if (upeek(pid, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2032                                 return -1;
2033                 }
2034         }
2035
2036 #elif defined(X86_64)
2037         {
2038                 int i;
2039                 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2040                         {RDI,RSI,RDX,R10,R8,R9},        /* x86-64 ABI */
2041                         {RBX,RCX,RDX,RDX,RSI,RDI,RBP}   /* i386 ABI */
2042                 };
2043
2044                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2045                         tcp->u_nargs = sysent[tcp->scno].nargs;
2046                 else
2047                         tcp->u_nargs = MAX_ARGS;
2048                 for (i = 0; i < tcp->u_nargs; i++) {
2049                         if (upeek(pid, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
2050                                 return -1;
2051                 }
2052         }
2053 #else /* Other architecture (like i386) (32bits specific) */
2054         {
2055                 int i;
2056                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2057                         tcp->u_nargs = sysent[tcp->scno].nargs;
2058                 else
2059                         tcp->u_nargs = MAX_ARGS;
2060                 for (i = 0; i < tcp->u_nargs; i++) {
2061                         if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
2062                                 return -1;
2063                 }
2064         }
2065 #endif
2066 #endif /* LINUX */
2067 #ifdef SUNOS4
2068         {
2069                 int i;
2070                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2071                         tcp->u_nargs = sysent[tcp->scno].nargs;
2072                 else
2073                         tcp->u_nargs = MAX_ARGS;
2074                 for (i = 0; i < tcp->u_nargs; i++) {
2075                         struct user *u;
2076
2077                         if (upeek(pid, uoff(u_arg[0]) +
2078                             (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2079                                 return -1;
2080                 }
2081         }
2082 #endif /* SUNOS4 */
2083 #ifdef SVR4
2084 #ifdef MIPS
2085         /*
2086          * SGI is broken: even though it has pr_sysarg, it doesn't
2087          * set them on system call entry.  Get a clue.
2088          */
2089         if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2090                 tcp->u_nargs = sysent[tcp->scno].nargs;
2091         else
2092                 tcp->u_nargs = tcp->status.pr_nsysarg;
2093         if (tcp->u_nargs > 4) {
2094                 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2095                         4*sizeof(tcp->u_arg[0]));
2096                 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2097                         (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2098         }
2099         else {
2100                 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2101                         tcp->u_nargs*sizeof(tcp->u_arg[0]));
2102         }
2103 #elif UNIXWARE >= 2
2104         /*
2105          * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2106          */
2107         if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2108                 tcp->u_nargs = sysent[tcp->scno].nargs;
2109         else
2110                 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2111         umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2112                 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2113 #elif defined (HAVE_PR_SYSCALL)
2114         if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2115                 tcp->u_nargs = sysent[tcp->scno].nargs;
2116         else
2117                 tcp->u_nargs = tcp->status.pr_nsysarg;
2118         {
2119                 int i;
2120                 for (i = 0; i < tcp->u_nargs; i++)
2121                         tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2122         }
2123 #elif defined (I386)
2124         if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2125                 tcp->u_nargs = sysent[tcp->scno].nargs;
2126         else
2127                 tcp->u_nargs = 5;
2128         umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2129                 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2130 #else
2131         I DONT KNOW WHAT TO DO
2132 #endif /* !HAVE_PR_SYSCALL */
2133 #endif /* SVR4 */
2134 #ifdef FREEBSD
2135         if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2136             sysent[tcp->scno].nargs > tcp->status.val)
2137                 tcp->u_nargs = sysent[tcp->scno].nargs;
2138         else
2139                 tcp->u_nargs = tcp->status.val;
2140         if (tcp->u_nargs < 0)
2141                 tcp->u_nargs = 0;
2142         if (tcp->u_nargs > MAX_ARGS)
2143                 tcp->u_nargs = MAX_ARGS;
2144         switch(regs.r_eax) {
2145         case SYS___syscall:
2146                 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2147                       regs.r_esp + sizeof(int) + sizeof(quad_t));
2148           break;
2149         case SYS_syscall:
2150                 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2151                       regs.r_esp + 2 * sizeof(int));
2152           break;
2153         default:
2154                 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2155                       regs.r_esp + sizeof(int));
2156           break;
2157         }
2158 #endif /* FREEBSD */
2159         return 1;
2160 }
2161
2162 int
2163 trace_syscall(tcp)
2164 struct tcb *tcp;
2165 {
2166         int sys_res;
2167         struct timeval tv;
2168         int res;
2169
2170         /* Measure the exit time as early as possible to avoid errors. */
2171         if (dtime && (tcp->flags & TCB_INSYSCALL))
2172                 gettimeofday(&tv, NULL);
2173
2174         res = get_scno(tcp);
2175         if (res != 1)
2176                 return res;
2177
2178         res = syscall_fixup(tcp);
2179         if (res != 1)
2180                 return res;
2181
2182         if (tcp->flags & TCB_INSYSCALL) {
2183                 long u_error;
2184                 res = get_error(tcp);
2185                 if (res != 1)
2186                         return res;
2187
2188                 internal_syscall(tcp);
2189                 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2190                     !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2191                         tcp->flags &= ~TCB_INSYSCALL;
2192                         return 0;
2193                 }
2194
2195                 if (tcp->flags & TCB_REPRINT) {
2196                         printleader(tcp);
2197                         tprintf("<... ");
2198                         if (tcp->scno >= nsyscalls || tcp->scno < 0)
2199                                 tprintf("syscall_%lu", tcp->scno);
2200                         else
2201                                 tprintf("%s", sysent[tcp->scno].sys_name);
2202                         tprintf(" resumed> ");
2203                 }
2204
2205                 if (cflag && tcp->scno < nsyscalls && tcp->scno >= 0) {
2206                         if (counts == NULL) {
2207                                 counts = calloc(sizeof *counts, nsyscalls);
2208                                 if (counts == NULL) {
2209                                         fprintf(stderr, "\
2210 strace: out of memory for call counts\n");
2211                                         exit(1);
2212                                 }
2213                         }
2214
2215                         counts[tcp->scno].calls++;
2216                         if (tcp->u_error)
2217                                 counts[tcp->scno].errors++;
2218                         tv_sub(&tv, &tv, &tcp->etime);
2219 #ifdef LINUX
2220                         if (tv_cmp(&tv, &tcp->dtime) > 0) {
2221                                 static struct timeval one_tick;
2222                                 if (one_tick.tv_usec == 0) {
2223                                         /* Initialize it.  */
2224                                         struct itimerval it;
2225                                         memset(&it, 0, sizeof it);
2226                                         it.it_interval.tv_usec = 1;
2227                                         setitimer(ITIMER_REAL, &it, NULL);
2228                                         getitimer(ITIMER_REAL, &it);
2229                                         one_tick = it.it_interval;
2230                                 }
2231
2232                                 if (tv_nz(&tcp->dtime))
2233                                         tv = tcp->dtime;
2234                                 else if (tv_cmp(&tv, &one_tick) > 0) {
2235                                         if (tv_cmp(&shortest, &one_tick) < 0)
2236                                                 tv = shortest;
2237                                         else
2238                                                 tv = one_tick;
2239                                 }
2240                         }
2241 #endif /* LINUX */
2242                         if (tv_cmp(&tv, &shortest) < 0)
2243                                 shortest = tv;
2244                         tv_add(&counts[tcp->scno].time,
2245                                 &counts[tcp->scno].time, &tv);
2246                         tcp->flags &= ~TCB_INSYSCALL;
2247                         return 0;
2248                 }
2249
2250                 if (tcp->scno >= nsyscalls || tcp->scno < 0
2251                     || (qual_flags[tcp->scno] & QUAL_RAW))
2252                         sys_res = printargs(tcp);
2253                 else {
2254                         if (not_failing_only && tcp->u_error)
2255                                 return 0;       /* ignore failed syscalls */
2256                         sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2257                 }
2258                 u_error = tcp->u_error;
2259                 tprintf(") ");
2260                 tabto(acolumn);
2261                 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2262                     qual_flags[tcp->scno] & QUAL_RAW) {
2263                         if (u_error)
2264                                 tprintf("= -1 (errno %ld)", u_error);
2265                         else
2266                                 tprintf("= %#lx", tcp->u_rval);
2267                 }
2268                 else if (!(sys_res & RVAL_NONE) && u_error) {
2269                         switch (u_error) {
2270 #ifdef LINUX
2271                         case ERESTARTSYS:
2272                                 tprintf("= ? ERESTARTSYS (To be restarted)");
2273                                 break;
2274                         case ERESTARTNOINTR:
2275                                 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2276                                 break;
2277                         case ERESTARTNOHAND:
2278                                 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2279                                 break;
2280                         case ERESTART_RESTARTBLOCK:
2281                                 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2282                                 break;
2283 #endif /* LINUX */
2284                         default:
2285                                 tprintf("= -1 ");
2286                                 if (u_error < 0)
2287                                         tprintf("E??? (errno %ld)", u_error);
2288                                 else if (u_error < nerrnos)
2289                                         tprintf("%s (%s)", errnoent[u_error],
2290                                                 strerror(u_error));
2291                                 else
2292                                         tprintf("ERRNO_%ld (%s)", u_error,
2293                                                 strerror(u_error));
2294                                 break;
2295                         }
2296                 }
2297                 else {
2298                         if (sys_res & RVAL_NONE)
2299                                 tprintf("= ?");
2300                         else {
2301                                 switch (sys_res & RVAL_MASK) {
2302                                 case RVAL_HEX:
2303                                         tprintf("= %#lx", tcp->u_rval);
2304                                         break;
2305                                 case RVAL_OCTAL:
2306                                         tprintf("= %#lo", tcp->u_rval);
2307                                         break;
2308                                 case RVAL_UDECIMAL:
2309                                         tprintf("= %lu", tcp->u_rval);
2310                                         break;
2311                                 case RVAL_DECIMAL:
2312                                         tprintf("= %ld", tcp->u_rval);
2313                                         break;
2314 #ifdef HAVE_LONG_LONG
2315                                 case RVAL_LHEX:
2316                                         tprintf("= %#llx", tcp->u_lrval);
2317                                         break;
2318                                 case RVAL_LOCTAL:
2319                                         tprintf("= %#llo", tcp->u_lrval);
2320                                         break;
2321                                 case RVAL_LUDECIMAL:
2322                                         tprintf("= %llu", tcp->u_lrval);
2323                                         break;
2324                                 case RVAL_LDECIMAL:
2325                                         tprintf("= %lld", tcp->u_lrval);
2326                                         break;
2327 #endif
2328                                 default:
2329                                         fprintf(stderr,
2330                                                 "invalid rval format\n");
2331                                         break;
2332                                 }
2333                         }
2334                         if ((sys_res & RVAL_STR) && tcp->auxstr)
2335                                 tprintf(" (%s)", tcp->auxstr);
2336                 }
2337                 if (dtime) {
2338                         tv_sub(&tv, &tv, &tcp->etime);
2339                         tprintf(" <%ld.%06ld>",
2340                                 (long) tv.tv_sec, (long) tv.tv_usec);
2341                 }
2342                 printtrailer(tcp);
2343
2344                 dumpio(tcp);
2345                 if (fflush(tcp->outf) == EOF)
2346                         return -1;
2347                 tcp->flags &= ~TCB_INSYSCALL;
2348                 return 0;
2349         }
2350
2351         /* Entering system call */
2352         res = syscall_enter(tcp);
2353         if (res != 1)
2354                 return res;
2355
2356         switch (tcp->scno + NR_SYSCALL_BASE) {
2357 #ifdef LINUX
2358 #if !defined (ALPHA) && !defined(SPARC) && !defined(SPARC64) && !defined(MIPS) && !defined(HPPA) && !defined(X86_64)
2359         case SYS_socketcall:
2360                 decode_subcall(tcp, SYS_socket_subcall,
2361                         SYS_socket_nsubcalls, deref_style);
2362                 break;
2363         case SYS_ipc:
2364                 decode_subcall(tcp, SYS_ipc_subcall,
2365                         SYS_ipc_nsubcalls, shift_style);
2366                 break;
2367 #endif /* !ALPHA && !MIPS && !SPARC && !SPARC64 && !HPPA && !X86_64 */
2368 #if defined (SPARC) || defined (SPARC64)
2369         case SYS_socketcall:
2370                 sparc_socket_decode (tcp);
2371                 break;
2372 #endif
2373 #endif /* LINUX */
2374 #ifdef SVR4
2375 #ifdef SYS_pgrpsys_subcall
2376         case SYS_pgrpsys:
2377                 decode_subcall(tcp, SYS_pgrpsys_subcall,
2378                         SYS_pgrpsys_nsubcalls, shift_style);
2379                 break;
2380 #endif /* SYS_pgrpsys_subcall */
2381 #ifdef SYS_sigcall_subcall
2382         case SYS_sigcall:
2383                 decode_subcall(tcp, SYS_sigcall_subcall,
2384                         SYS_sigcall_nsubcalls, mask_style);
2385                 break;
2386 #endif /* SYS_sigcall_subcall */
2387         case SYS_msgsys:
2388                 decode_subcall(tcp, SYS_msgsys_subcall,
2389                         SYS_msgsys_nsubcalls, shift_style);
2390                 break;
2391         case SYS_shmsys:
2392                 decode_subcall(tcp, SYS_shmsys_subcall,
2393                         SYS_shmsys_nsubcalls, shift_style);
2394                 break;
2395         case SYS_semsys:
2396                 decode_subcall(tcp, SYS_semsys_subcall,
2397                         SYS_semsys_nsubcalls, shift_style);
2398                 break;
2399 #if 0 /* broken */
2400         case SYS_utssys:
2401                 decode_subcall(tcp, SYS_utssys_subcall,
2402                         SYS_utssys_nsubcalls, shift_style);
2403                 break;
2404 #endif
2405         case SYS_sysfs:
2406                 decode_subcall(tcp, SYS_sysfs_subcall,
2407                         SYS_sysfs_nsubcalls, shift_style);
2408                 break;
2409         case SYS_spcall:
2410                 decode_subcall(tcp, SYS_spcall_subcall,
2411                         SYS_spcall_nsubcalls, shift_style);
2412                 break;
2413 #ifdef SYS_context_subcall
2414         case SYS_context:
2415                 decode_subcall(tcp, SYS_context_subcall,
2416                         SYS_context_nsubcalls, shift_style);
2417                 break;
2418 #endif /* SYS_context_subcall */
2419 #ifdef SYS_door_subcall
2420         case SYS_door:
2421                 decode_subcall(tcp, SYS_door_subcall,
2422                         SYS_door_nsubcalls, door_style);
2423                 break;
2424 #endif /* SYS_door_subcall */
2425 #ifdef SYS_kaio_subcall
2426         case SYS_kaio:
2427                 decode_subcall(tcp, SYS_kaio_subcall,
2428                         SYS_kaio_nsubcalls, shift_style);
2429                 break;
2430 #endif
2431 #endif /* SVR4 */
2432 #ifdef FREEBSD
2433         case SYS_msgsys:
2434         case SYS_shmsys:
2435         case SYS_semsys:
2436                 decode_subcall(tcp, 0, 0, table_style);
2437                 break;
2438 #endif
2439 #ifdef SUNOS4
2440         case SYS_semsys:
2441                 decode_subcall(tcp, SYS_semsys_subcall,
2442                         SYS_semsys_nsubcalls, shift_style);
2443                 break;
2444         case SYS_msgsys:
2445                 decode_subcall(tcp, SYS_msgsys_subcall,
2446                         SYS_msgsys_nsubcalls, shift_style);
2447                 break;
2448         case SYS_shmsys:
2449                 decode_subcall(tcp, SYS_shmsys_subcall,
2450                         SYS_shmsys_nsubcalls, shift_style);
2451                 break;
2452 #endif
2453         }
2454
2455         internal_syscall(tcp);
2456         if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2457                 tcp->flags |= TCB_INSYSCALL;
2458                 return 0;
2459         }
2460
2461         if (cflag) {
2462                 gettimeofday(&tcp->etime, NULL);
2463                 tcp->flags |= TCB_INSYSCALL;
2464                 return 0;
2465         }
2466
2467         printleader(tcp);
2468         tcp->flags &= ~TCB_REPRINT;
2469         tcp_last = tcp;
2470         if (tcp->scno >= nsyscalls || tcp->scno < 0)
2471                 tprintf("syscall_%lu(", tcp->scno);
2472         else
2473                 tprintf("%s(", sysent[tcp->scno].sys_name);
2474         if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2475             ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2476                 sys_res = printargs(tcp);
2477         else
2478                 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2479         if (fflush(tcp->outf) == EOF)
2480                 return -1;
2481         tcp->flags |= TCB_INSYSCALL;
2482         /* Measure the entrance time as late as possible to avoid errors. */
2483         if (dtime)
2484                 gettimeofday(&tcp->etime, NULL);
2485         return sys_res;
2486 }
2487
2488 int
2489 printargs(tcp)
2490 struct tcb *tcp;
2491 {
2492         if (entering(tcp)) {
2493                 int i;
2494
2495                 for (i = 0; i < tcp->u_nargs; i++)
2496                         tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2497         }
2498         return 0;
2499 }
2500
2501 long
2502 getrval2(tcp)
2503 struct tcb *tcp;
2504 {
2505         long val = -1;
2506
2507 #ifdef LINUX
2508 #if defined (SPARC) || defined (SPARC64)
2509         struct regs regs;
2510         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
2511                 return -1;
2512         val = regs.r_o1;
2513 #elif defined(SH)
2514         if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
2515                 return -1;
2516 #endif /* SPARC || SPARC64 */
2517 #elif defined(IA64)
2518         if (upeek(tcp->pid, PT_R9, &val) < 0)
2519                 return -1;
2520 #endif /* LINUX */
2521
2522 #ifdef SUNOS4
2523         if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
2524                 return -1;
2525 #endif /* SUNOS4 */
2526
2527 #ifdef SVR4
2528 #ifdef SPARC
2529         val = tcp->status.PR_REG[R_O1];
2530 #endif /* SPARC */
2531 #ifdef I386
2532         val = tcp->status.PR_REG[EDX];
2533 #endif /* I386 */
2534 #ifdef X86_64
2535         val = tcp->status.PR_REG[RDX];
2536 #endif /* X86_64 */
2537 #ifdef MIPS
2538         val = tcp->status.PR_REG[CTX_V1];
2539 #endif /* MIPS */
2540 #endif /* SVR4 */
2541 #ifdef FREEBSD
2542         struct reg regs;
2543         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2544         val = regs.r_edx;
2545 #endif
2546         return val;
2547 }
2548
2549 /*
2550  * Apparently, indirect system calls have already be converted by ptrace(2),
2551  * so if you see "indir" this program has gone astray.
2552  */
2553 int
2554 sys_indir(tcp)
2555 struct tcb *tcp;
2556 {
2557         int i, scno, nargs;
2558
2559         if (entering(tcp)) {
2560                 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2561                         fprintf(stderr, "Bogus syscall: %u\n", scno);
2562                         return 0;
2563                 }
2564                 nargs = sysent[scno].nargs;
2565                 tprintf("%s", sysent[scno].sys_name);
2566                 for (i = 0; i < nargs; i++)
2567                         tprintf(", %#lx", tcp->u_arg[i+1]);
2568         }
2569         return 0;
2570 }
2571
2572 static int
2573 time_cmp(a, b)
2574 void *a;
2575 void *b;
2576 {
2577         return -tv_cmp(&counts[*((int *) a)].time, &counts[*((int *) b)].time);
2578 }
2579
2580 static int
2581 syscall_cmp(a, b)
2582 void *a;
2583 void *b;
2584 {
2585         return strcmp(sysent[*((int *) a)].sys_name,
2586                 sysent[*((int *) b)].sys_name);
2587 }
2588
2589 static int
2590 count_cmp(a, b)
2591 void *a;
2592 void *b;
2593 {
2594         int m = counts[*((int *) a)].calls, n = counts[*((int *) b)].calls;
2595
2596         return (m < n) ? 1 : (m > n) ? -1 : 0;
2597 }
2598
2599 static int (*sortfun)();
2600 static struct timeval overhead = { -1, -1 };
2601
2602 void
2603 set_sortby(sortby)
2604 char *sortby;
2605 {
2606         if (strcmp(sortby, "time") == 0)
2607                 sortfun = time_cmp;
2608         else if (strcmp(sortby, "calls") == 0)
2609                 sortfun = count_cmp;
2610         else if (strcmp(sortby, "name") == 0)
2611                 sortfun = syscall_cmp;
2612         else if (strcmp(sortby, "nothing") == 0)
2613                 sortfun = NULL;
2614         else {
2615                 fprintf(stderr, "invalid sortby: `%s'\n", sortby);
2616                 exit(1);
2617         }
2618 }
2619
2620 void set_overhead(n)
2621 int n;
2622 {
2623         overhead.tv_sec = n / 1000000;
2624         overhead.tv_usec = n % 1000000;
2625 }
2626
2627 void
2628 call_summary(outf)
2629 FILE *outf;
2630 {
2631         int i, j;
2632         int call_cum, error_cum;
2633         struct timeval tv_cum, dtv;
2634         double percent;
2635         char *dashes = "-------------------------";
2636         char error_str[16];
2637
2638         int *sorted_count = malloc(nsyscalls * sizeof(int));
2639
2640         call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
2641         if (overhead.tv_sec == -1) {
2642                 tv_mul(&overhead, &shortest, 8);
2643                 tv_div(&overhead, &overhead, 10);
2644         }
2645         for (i = 0; i < nsyscalls; i++) {
2646                 sorted_count[i] = i;
2647                 if (counts == NULL || counts[i].calls == 0)
2648                         continue;
2649                 tv_mul(&dtv, &overhead, counts[i].calls);
2650                 tv_sub(&counts[i].time, &counts[i].time, &dtv);
2651                 call_cum += counts[i].calls;
2652                 error_cum += counts[i].errors;
2653                 tv_add(&tv_cum, &tv_cum, &counts[i].time);
2654         }
2655         if (sortfun)
2656                 qsort((void *) sorted_count, nsyscalls, sizeof(int), sortfun);
2657         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",
2658                 "% time", "seconds", "usecs/call",
2659                 "calls", "errors", "syscall");
2660         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2661                 dashes, dashes, dashes, dashes, dashes, dashes);
2662         if (counts) {
2663                 for (i = 0; i < nsyscalls; i++) {
2664                         j = sorted_count[i];
2665                         if (counts[j].calls == 0)
2666                                 continue;
2667                         tv_div(&dtv, &counts[j].time, counts[j].calls);
2668                         if (counts[j].errors)
2669                                 sprintf(error_str, "%d", counts[j].errors);
2670                         else
2671                                 error_str[0] = '\0';
2672                         percent = (100.0 * tv_float(&counts[j].time)
2673                                    / tv_float(&tv_cum));
2674                         fprintf(outf, "%6.2f %4ld.%06ld %11ld %9d %9.9s %s\n",
2675                                 percent, (long) counts[j].time.tv_sec,
2676                                 (long) counts[j].time.tv_usec,
2677                                 (long) 1000000 * dtv.tv_sec + dtv.tv_usec,
2678                                 counts[j].calls,
2679                                 error_str, sysent[j].sys_name);
2680                 }
2681         }
2682         free(sorted_count);
2683
2684         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2685                 dashes, dashes, dashes, dashes, dashes, dashes);
2686         if (error_cum)
2687                 sprintf(error_str, "%d", error_cum);
2688         else
2689                 error_str[0] = '\0';
2690         fprintf(outf, "%6.6s %4ld.%06ld %11.11s %9d %9.9s %s\n",
2691                 "100.00", (long) tv_cum.tv_sec, (long) tv_cum.tv_usec, "",
2692                 call_cum, error_str, "total");
2693
2694 }