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