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