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