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