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