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 /*
1017 * Note: we only deal with only 32-bit CPUs here.
1018 */
1019 if (regs.ARM_cpsr & 0x20) {
1020 /*
1021 * Get the Thumb-mode system call number
1022 */
1023 scno = regs.ARM_r7;
1024 } else {
1025 /*
1026 * Get the ARM-mode system call number
1027 */
1028 errno = 0;
1029 scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
1030 if (errno)
1031 return -1;
1032
1033 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1034 tcp->flags &= ~TCB_WAITEXECVE;
1035 return 0;
1036 }
1037
1038 /* Handle the EABI syscall convention. We do not
1039 bother converting structures between the two
1040 ABIs, but basic functionality should work even
1041 if strace and the traced program have different
1042 ABIs. */
1043 if (scno == 0xef000000) {
1044 scno = regs.ARM_r7;
1045 } else {
1046 if ((scno & 0x0ff00000) != 0x0f900000) {
1047 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1048 scno);
1049 return -1;
1050 }
1051
1052 /*
1053 * Fixup the syscall number
1054 */
1055 scno &= 0x000fffff;
1056 }
1057 }
1058
1059 if (tcp->flags & TCB_INSYSCALL) {
1060 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1061 tcp->flags &= ~TCB_INSYSCALL;
1062 }
1063 } else {
1064 if (!(tcp->flags & TCB_INSYSCALL)) {
1065 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1066 tcp->flags |= TCB_INSYSCALL;
1067 }
1068 }
1069 #elif defined (M68K)
1070 if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
1071 return -1;
1072 #elif defined (MIPS)
1073 if (upeek(pid, REG_A3, &a3) < 0)
1074 return -1;
1075
1076 if(!(tcp->flags & TCB_INSYSCALL)) {
1077 if (upeek(pid, REG_V0, &scno) < 0)
1078 return -1;
1079
1080 if (scno < 0 || scno > nsyscalls) {
1081 if(a3 == 0 || a3 == -1) {
1082 if(debug)
1083 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1084 return 0;
1085 }
1086 }
1087 } else {
1088 if (upeek(pid, REG_V0, &r2) < 0)
1089 return -1;
1090 }
1091 #elif defined (ALPHA)
1092 if (upeek(pid, REG_A3, &a3) < 0)
1093 return -1;
1094
1095 if (!(tcp->flags & TCB_INSYSCALL)) {
1096 if (upeek(pid, REG_R0, &scno) < 0)
1097 return -1;
1098
1099 /* Check if we return from execve. */
1100 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1101 tcp->flags &= ~TCB_WAITEXECVE;
1102 return 0;
1103 }
1104
1105 /*
1106 * Do some sanity checks to figure out if it's
1107 * really a syscall entry
1108 */
1109 if (scno < 0 || scno > nsyscalls) {
1110 if (a3 == 0 || a3 == -1) {
1111 if (debug)
1112 fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1113 return 0;
1114 }
1115 }
1116 }
1117 else {
1118 if (upeek(pid, REG_R0, &r0) < 0)
1119 return -1;
1120 }
1121 #elif defined (SPARC) || defined (SPARC64)
1122 /* Everything we need is in the current register set. */
1123 if (ptrace(PTRACE_GETREGS,pid,(char *)®s,0) < 0)
1124 return -1;
1125
1126 /* If we are entering, then disassemble the syscall trap. */
1127 if (!(tcp->flags & TCB_INSYSCALL)) {
1128 /* Retrieve the syscall trap instruction. */
1129 errno = 0;
1130 trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
1131 #if defined(SPARC64)
1132 trap >>= 32;
1133 #endif
1134 if (errno)
1135 return -1;
1136
1137 /* Disassemble the trap to see what personality to use. */
1138 switch (trap) {
1139 case 0x91d02010:
1140 /* Linux/SPARC syscall trap. */
1141 set_personality(0);
1142 break;
1143 case 0x91d0206d:
1144 /* Linux/SPARC64 syscall trap. */
1145 set_personality(2);
1146 break;
1147 case 0x91d02000:
1148 /* SunOS syscall trap. (pers 1) */
1149 fprintf(stderr,"syscall: SunOS no support\n");
1150 return -1;
1151 case 0x91d02008:
1152 /* Solaris 2.x syscall trap. (per 2) */
1153 set_personality(1);
1154 break;
1155 case 0x91d02009:
1156 /* NetBSD/FreeBSD syscall trap. */
1157 fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1158 return -1;
1159 case 0x91d02027:
1160 /* Solaris 2.x gettimeofday */
1161 set_personality(1);
1162 break;
1163 default:
1164 /* Unknown syscall trap. */
1165 if(tcp->flags & TCB_WAITEXECVE) {
1166 tcp->flags &= ~TCB_WAITEXECVE;
1167 return 0;
1168 }
1169 #if defined (SPARC64)
1170 fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc);
1171 #else
1172 fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
1173 #endif
1174 return -1;
1175 }
1176
1177 /* Extract the system call number from the registers. */
1178 if (trap == 0x91d02027)
1179 scno = 156;
1180 else
1181 scno = regs.r_g1;
1182 if (scno == 0) {
1183 scno = regs.r_o0;
1184 memmove (®s.r_o0, ®s.r_o1, 7*sizeof(regs.r_o0));
1185 }
1186 }
1187 #elif defined(HPPA)
1188 if (upeek(pid, PT_GR20, &scno) < 0)
1189 return -1;
1190 if (!(tcp->flags & TCB_INSYSCALL)) {
1191 /* Check if we return from execve. */
1192 if ((tcp->flags & TCB_WAITEXECVE)) {
1193 tcp->flags &= ~TCB_WAITEXECVE;
1194 return 0;
1195 }
1196 }
1197 #elif defined(SH)
1198 /*
1199 * In the new syscall ABI, the system call number is in R3.
1200 */
1201 if (upeek(pid, 4*(REG_REG0+3), &scno) < 0)
1202 return -1;
1203
1204 if (scno < 0) {
1205 /* Odd as it may seem, a glibc bug has been known to cause
1206 glibc to issue bogus negative syscall numbers. So for
1207 our purposes, make strace print what it *should* have been */
1208 long correct_scno = (scno & 0xff);
1209 if (debug)
1210 fprintf(stderr,
1211 "Detected glibc bug: bogus system call number = %ld, "
1212 "correcting to %ld\n",
1213 scno,
1214 correct_scno);
1215 scno = correct_scno;
1216 }
1217
1218
1219 if (!(tcp->flags & TCB_INSYSCALL)) {
1220 /* Check if we return from execve. */
1221 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1222 tcp->flags &= ~TCB_WAITEXECVE;
1223 return 0;
1224 }
1225 }
1226 #elif defined(SH64)
1227 if (upeek(pid, REG_SYSCALL, &scno) < 0)
1228 return -1;
1229 scno &= 0xFFFF;
1230
1231 if (!(tcp->flags & TCB_INSYSCALL)) {
1232 /* Check if we return from execve. */
1233 if (tcp->flags & TCB_WAITEXECVE) {
1234 tcp->flags &= ~TCB_WAITEXECVE;
1235 return 0;
1236 }
1237 }
1238 #endif /* SH64 */
1239 #endif /* LINUX */
1240 #ifdef SUNOS4
1241 if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
1242 return -1;
1243 #elif defined(SH)
1244 /* new syscall ABI returns result in R0 */
1245 if (upeek(pid, 4*REG_REG0, (long *)&r0) < 0)
1246 return -1;
1247 #elif defined(SH64)
1248 /* ABI defines result returned in r9 */
1249 if (upeek(pid, REG_GENERAL(9), (long *)&r9) < 0)
1250 return -1;
1251
1252 #endif
1253 #ifdef USE_PROCFS
1254 #ifdef HAVE_PR_SYSCALL
1255 scno = tcp->status.PR_SYSCALL;
1256 #else /* !HAVE_PR_SYSCALL */
1257 #ifndef FREEBSD
1258 scno = tcp->status.PR_WHAT;
1259 #else /* FREEBSD */
1260 if (pread(tcp->pfd_reg, ®s, sizeof(regs), 0) < 0) {
1261 perror("pread");
1262 return -1;
1263 }
1264 switch (regs.r_eax) {
1265 case SYS_syscall:
1266 case SYS___syscall:
1267 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1268 break;
1269 default:
1270 scno = regs.r_eax;
1271 break;
1272 }
1273 #endif /* FREEBSD */
1274 #endif /* !HAVE_PR_SYSCALL */
1275 #endif /* USE_PROCFS */
1276 if (!(tcp->flags & TCB_INSYSCALL))
1277 tcp->scno = scno;
1278 return 1;
1279 }
1280
1281
1282 long
known_scno(tcp)1283 known_scno(tcp)
1284 struct tcb *tcp;
1285 {
1286 long scno = tcp->scno;
1287 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1288 scno = sysent[scno].native_scno;
1289 else
1290 scno += NR_SYSCALL_BASE;
1291 return scno;
1292 }
1293
1294 static int
syscall_fixup(tcp)1295 syscall_fixup(tcp)
1296 struct tcb *tcp;
1297 {
1298 #ifndef USE_PROCFS
1299 int pid = tcp->pid;
1300 #else /* USE_PROCFS */
1301 int scno = known_scno(tcp);
1302
1303 if (!(tcp->flags & TCB_INSYSCALL)) {
1304 if (tcp->status.PR_WHY != PR_SYSENTRY) {
1305 if (
1306 scno == SYS_fork
1307 #ifdef SYS_vfork
1308 || scno == SYS_vfork
1309 #endif /* SYS_vfork */
1310 #ifdef SYS_fork1
1311 || scno == SYS_fork1
1312 #endif /* SYS_fork1 */
1313 #ifdef SYS_forkall
1314 || scno == SYS_forkall
1315 #endif /* SYS_forkall */
1316 #ifdef SYS_rfork1
1317 || scno == SYS_rfork1
1318 #endif /* SYS_fork1 */
1319 #ifdef SYS_rforkall
1320 || scno == SYS_rforkall
1321 #endif /* SYS_rforkall */
1322 ) {
1323 /* We are returning in the child, fake it. */
1324 tcp->status.PR_WHY = PR_SYSENTRY;
1325 trace_syscall(tcp);
1326 tcp->status.PR_WHY = PR_SYSEXIT;
1327 }
1328 else {
1329 fprintf(stderr, "syscall: missing entry\n");
1330 tcp->flags |= TCB_INSYSCALL;
1331 }
1332 }
1333 }
1334 else {
1335 if (tcp->status.PR_WHY != PR_SYSEXIT) {
1336 fprintf(stderr, "syscall: missing exit\n");
1337 tcp->flags &= ~TCB_INSYSCALL;
1338 }
1339 }
1340 #endif /* USE_PROCFS */
1341 #ifdef SUNOS4
1342 if (!(tcp->flags & TCB_INSYSCALL)) {
1343 if (scno == 0) {
1344 fprintf(stderr, "syscall: missing entry\n");
1345 tcp->flags |= TCB_INSYSCALL;
1346 }
1347 }
1348 else {
1349 if (scno != 0) {
1350 if (debug) {
1351 /*
1352 * This happens when a signal handler
1353 * for a signal which interrupted a
1354 * a system call makes another system call.
1355 */
1356 fprintf(stderr, "syscall: missing exit\n");
1357 }
1358 tcp->flags &= ~TCB_INSYSCALL;
1359 }
1360 }
1361 #endif /* SUNOS4 */
1362 #ifdef LINUX
1363 #if defined (I386)
1364 if (upeek(pid, 4*EAX, &eax) < 0)
1365 return -1;
1366 if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1367 if (debug)
1368 fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1369 return 0;
1370 }
1371 #elif defined (X86_64)
1372 if (upeek(pid, 8*RAX, &rax) < 0)
1373 return -1;
1374 if (current_personality == 1)
1375 rax = (long int)(int)rax; /* sign extend from 32 bits */
1376 if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1377 if (debug)
1378 fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1379 return 0;
1380 }
1381 #elif defined (S390) || defined (S390X)
1382 if (upeek(pid, PT_GPR2, &gpr2) < 0)
1383 return -1;
1384 if (syscall_mode != -ENOSYS)
1385 syscall_mode = tcp->scno;
1386 if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
1387 if (debug)
1388 fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1389 return 0;
1390 }
1391 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1392 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1393 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1394 /*
1395 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1396 * flag set for the post-execve SIGTRAP to see and reset.
1397 */
1398 gpr2 = 0;
1399 }
1400 #elif defined (POWERPC)
1401 # define SO_MASK 0x10000000
1402 if (upeek(pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1403 return -1;
1404 if (upeek(pid, sizeof(unsigned long)*PT_R3, &result) < 0)
1405 return -1;
1406 if (flags & SO_MASK)
1407 result = -result;
1408 #elif defined (M68K)
1409 if (upeek(pid, 4*PT_D0, &d0) < 0)
1410 return -1;
1411 if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1412 if (debug)
1413 fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1414 return 0;
1415 }
1416 #elif defined (ARM)
1417 /*
1418 * Nothing required
1419 */
1420 #elif defined (HPPA)
1421 if (upeek(pid, PT_GR28, &r28) < 0)
1422 return -1;
1423 #elif defined(IA64)
1424 if (upeek(pid, PT_R10, &r10) < 0)
1425 return -1;
1426 if (upeek(pid, PT_R8, &r8) < 0)
1427 return -1;
1428 if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1429 if (debug)
1430 fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1431 return 0;
1432 }
1433 #endif
1434 #endif /* LINUX */
1435 return 1;
1436 }
1437
1438 static int
get_error(tcp)1439 get_error(tcp)
1440 struct tcb *tcp;
1441 {
1442 int u_error = 0;
1443 #ifdef LINUX
1444 #if defined(S390) || defined(S390X)
1445 if (gpr2 && (unsigned) -gpr2 < nerrnos) {
1446 tcp->u_rval = -1;
1447 u_error = -gpr2;
1448 }
1449 else {
1450 tcp->u_rval = gpr2;
1451 u_error = 0;
1452 }
1453 #else /* !S390 && !S390X */
1454 #ifdef I386
1455 if (eax < 0 && -eax < nerrnos) {
1456 tcp->u_rval = -1;
1457 u_error = -eax;
1458 }
1459 else {
1460 tcp->u_rval = eax;
1461 u_error = 0;
1462 }
1463 #else /* !I386 */
1464 #ifdef X86_64
1465 if (rax < 0 && -rax < nerrnos) {
1466 tcp->u_rval = -1;
1467 u_error = -rax;
1468 }
1469 else {
1470 tcp->u_rval = rax;
1471 u_error = 0;
1472 }
1473 #else
1474 #ifdef IA64
1475 if (ia32) {
1476 int err;
1477
1478 err = (int)r8;
1479 if (err < 0 && -err < nerrnos) {
1480 tcp->u_rval = -1;
1481 u_error = -err;
1482 }
1483 else {
1484 tcp->u_rval = err;
1485 u_error = 0;
1486 }
1487 } else {
1488 if (r10) {
1489 tcp->u_rval = -1;
1490 u_error = r8;
1491 } else {
1492 tcp->u_rval = r8;
1493 u_error = 0;
1494 }
1495 }
1496 #else /* !IA64 */
1497 #ifdef MIPS
1498 if (a3) {
1499 tcp->u_rval = -1;
1500 u_error = r2;
1501 } else {
1502 tcp->u_rval = r2;
1503 u_error = 0;
1504 }
1505 #else
1506 #ifdef POWERPC
1507 if (result && (unsigned long) -result < nerrnos) {
1508 tcp->u_rval = -1;
1509 u_error = -result;
1510 }
1511 else {
1512 tcp->u_rval = result;
1513 u_error = 0;
1514 }
1515 #else /* !POWERPC */
1516 #ifdef M68K
1517 if (d0 && (unsigned) -d0 < nerrnos) {
1518 tcp->u_rval = -1;
1519 u_error = -d0;
1520 }
1521 else {
1522 tcp->u_rval = d0;
1523 u_error = 0;
1524 }
1525 #else /* !M68K */
1526 #ifdef ARM
1527 if (regs.ARM_r0 && (unsigned) -regs.ARM_r0 < nerrnos) {
1528 tcp->u_rval = -1;
1529 u_error = -regs.ARM_r0;
1530 }
1531 else {
1532 tcp->u_rval = regs.ARM_r0;
1533 u_error = 0;
1534 }
1535 #else /* !ARM */
1536 #ifdef ALPHA
1537 if (a3) {
1538 tcp->u_rval = -1;
1539 u_error = r0;
1540 }
1541 else {
1542 tcp->u_rval = r0;
1543 u_error = 0;
1544 }
1545 #else /* !ALPHA */
1546 #ifdef SPARC
1547 if (regs.r_psr & PSR_C) {
1548 tcp->u_rval = -1;
1549 u_error = regs.r_o0;
1550 }
1551 else {
1552 tcp->u_rval = regs.r_o0;
1553 u_error = 0;
1554 }
1555 #else /* !SPARC */
1556 #ifdef SPARC64
1557 if (regs.r_tstate & 0x1100000000UL) {
1558 tcp->u_rval = -1;
1559 u_error = regs.r_o0;
1560 }
1561 else {
1562 tcp->u_rval = regs.r_o0;
1563 u_error = 0;
1564 }
1565 #else /* !SPARC64 */
1566 #ifdef HPPA
1567 if (r28 && (unsigned) -r28 < nerrnos) {
1568 tcp->u_rval = -1;
1569 u_error = -r28;
1570 }
1571 else {
1572 tcp->u_rval = r28;
1573 u_error = 0;
1574 }
1575 #else
1576 #ifdef SH
1577 /* interpret R0 as return value or error number */
1578 if (r0 && (unsigned) -r0 < nerrnos) {
1579 tcp->u_rval = -1;
1580 u_error = -r0;
1581 }
1582 else {
1583 tcp->u_rval = r0;
1584 u_error = 0;
1585 }
1586 #else
1587 #ifdef SH64
1588 /* interpret result as return value or error number */
1589 if (r9 && (unsigned) -r9 < nerrnos) {
1590 tcp->u_rval = -1;
1591 u_error = -r9;
1592 }
1593 else {
1594 tcp->u_rval = r9;
1595 u_error = 0;
1596 }
1597 #endif /* SH64 */
1598 #endif /* SH */
1599 #endif /* HPPA */
1600 #endif /* SPARC */
1601 #endif /* SPARC64 */
1602 #endif /* ALPHA */
1603 #endif /* ARM */
1604 #endif /* M68K */
1605 #endif /* POWERPC */
1606 #endif /* MIPS */
1607 #endif /* IA64 */
1608 #endif /* X86_64 */
1609 #endif /* I386 */
1610 #endif /* S390 || S390X */
1611 #endif /* LINUX */
1612 #ifdef SUNOS4
1613 /* get error code from user struct */
1614 if (upeek(pid, uoff(u_error), &u_error) < 0)
1615 return -1;
1616 u_error >>= 24; /* u_error is a char */
1617
1618 /* get system call return value */
1619 if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
1620 return -1;
1621 #endif /* SUNOS4 */
1622 #ifdef SVR4
1623 #ifdef SPARC
1624 /* Judicious guessing goes a long way. */
1625 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1626 tcp->u_rval = -1;
1627 u_error = tcp->status.pr_reg[R_O0];
1628 }
1629 else {
1630 tcp->u_rval = tcp->status.pr_reg[R_O0];
1631 u_error = 0;
1632 }
1633 #endif /* SPARC */
1634 #ifdef I386
1635 /* Wanna know how to kill an hour single-stepping? */
1636 if (tcp->status.PR_REG[EFL] & 0x1) {
1637 tcp->u_rval = -1;
1638 u_error = tcp->status.PR_REG[EAX];
1639 }
1640 else {
1641 tcp->u_rval = tcp->status.PR_REG[EAX];
1642 #ifdef HAVE_LONG_LONG
1643 tcp->u_lrval =
1644 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1645 tcp->status.PR_REG[EAX];
1646 #endif
1647 u_error = 0;
1648 }
1649 #endif /* I386 */
1650 #ifdef X86_64
1651 /* Wanna know how to kill an hour single-stepping? */
1652 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1653 tcp->u_rval = -1;
1654 u_error = tcp->status.PR_REG[RAX];
1655 }
1656 else {
1657 tcp->u_rval = tcp->status.PR_REG[RAX];
1658 u_error = 0;
1659 }
1660 #endif /* X86_64 */
1661 #ifdef MIPS
1662 if (tcp->status.pr_reg[CTX_A3]) {
1663 tcp->u_rval = -1;
1664 u_error = tcp->status.pr_reg[CTX_V0];
1665 }
1666 else {
1667 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1668 u_error = 0;
1669 }
1670 #endif /* MIPS */
1671 #endif /* SVR4 */
1672 #ifdef FREEBSD
1673 if (regs.r_eflags & PSL_C) {
1674 tcp->u_rval = -1;
1675 u_error = regs.r_eax;
1676 } else {
1677 tcp->u_rval = regs.r_eax;
1678 tcp->u_lrval =
1679 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1680 u_error = 0;
1681 }
1682 #endif /* FREEBSD */
1683 tcp->u_error = u_error;
1684 return 1;
1685 }
1686
1687 int
force_result(tcp,error,rval)1688 force_result(tcp, error, rval)
1689 struct tcb *tcp;
1690 int error;
1691 long rval;
1692 {
1693 #ifdef LINUX
1694 #if defined(S390) || defined(S390X)
1695 gpr2 = error ? -error : rval;
1696 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1697 return -1;
1698 #else /* !S390 && !S390X */
1699 #ifdef I386
1700 eax = error ? -error : rval;
1701 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1702 return -1;
1703 #else /* !I386 */
1704 #ifdef X86_64
1705 rax = error ? -error : rval;
1706 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
1707 return -1;
1708 #else
1709 #ifdef IA64
1710 if (ia32) {
1711 r8 = error ? -error : rval;
1712 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1713 return -1;
1714 }
1715 else {
1716 if (error) {
1717 r8 = error;
1718 r10 = -1;
1719 }
1720 else {
1721 r8 = rval;
1722 r10 = 0;
1723 }
1724 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1725 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1726 return -1;
1727 }
1728 #else /* !IA64 */
1729 #ifdef MIPS
1730 if (error) {
1731 r2 = error;
1732 a3 = -1;
1733 }
1734 else {
1735 r2 = rval;
1736 a3 = 0;
1737 }
1738 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1739 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1740 return -1;
1741 #else
1742 #ifdef POWERPC
1743 if (upeek(tcp->pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1744 return -1;
1745 if (error) {
1746 flags |= SO_MASK;
1747 result = error;
1748 }
1749 else {
1750 flags &= ~SO_MASK;
1751 result = rval;
1752 }
1753 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1754 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
1755 return -1;
1756 #else /* !POWERPC */
1757 #ifdef M68K
1758 d0 = error ? -error : rval;
1759 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1760 return -1;
1761 #else /* !M68K */
1762 #ifdef ARM
1763 regs.ARM_r0 = error ? -error : rval;
1764 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
1765 return -1;
1766 #else /* !ARM */
1767 #ifdef ALPHA
1768 if (error) {
1769 a3 = -1;
1770 r0 = error;
1771 }
1772 else {
1773 a3 = 0;
1774 r0 = rval;
1775 }
1776 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1777 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1778 return -1;
1779 #else /* !ALPHA */
1780 #ifdef SPARC
1781 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0)
1782 return -1;
1783 if (error) {
1784 regs.r_psr |= PSR_C;
1785 regs.r_o0 = error;
1786 }
1787 else {
1788 regs.r_psr &= ~PSR_C;
1789 regs.r_o0 = rval;
1790 }
1791 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0)
1792 return -1;
1793 #else /* !SPARC */
1794 #ifdef SPARC64
1795 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0)
1796 return -1;
1797 if (error) {
1798 regs.r_tstate |= 0x1100000000UL;
1799 regs.r_o0 = error;
1800 }
1801 else {
1802 regs.r_tstate &= ~0x1100000000UL;
1803 regs.r_o0 = rval;
1804 }
1805 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0)
1806 return -1;
1807 #else /* !SPARC64 */
1808 #ifdef HPPA
1809 r28 = error ? -error : rval;
1810 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1811 return -1;
1812 #else
1813 #ifdef SH
1814 r0 = error ? -error : rval;
1815 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1816 return -1;
1817 #else
1818 #ifdef SH64
1819 r9 = error ? -error : rval;
1820 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1821 return -1;
1822 #endif /* SH64 */
1823 #endif /* SH */
1824 #endif /* HPPA */
1825 #endif /* SPARC */
1826 #endif /* SPARC64 */
1827 #endif /* ALPHA */
1828 #endif /* ARM */
1829 #endif /* M68K */
1830 #endif /* POWERPC */
1831 #endif /* MIPS */
1832 #endif /* IA64 */
1833 #endif /* X86_64 */
1834 #endif /* I386 */
1835 #endif /* S390 || S390X */
1836 #endif /* LINUX */
1837 #ifdef SUNOS4
1838 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1839 error << 24) < 0 ||
1840 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1841 return -1;
1842 #endif /* SUNOS4 */
1843 #ifdef SVR4
1844 /* XXX no clue */
1845 return -1;
1846 #endif /* SVR4 */
1847 #ifdef FREEBSD
1848 if (pread(tcp->pfd_reg, ®s, sizeof(regs), 0) < 0) {
1849 perror("pread");
1850 return -1;
1851 }
1852 if (error) {
1853 regs.r_eflags |= PSL_C;
1854 regs.r_eax = error;
1855 }
1856 else {
1857 regs.r_eflags &= ~PSL_C;
1858 regs.r_eax = rval;
1859 }
1860 if (pwrite(tcp->pfd_reg, ®s, sizeof(regs), 0) < 0) {
1861 perror("pwrite");
1862 return -1;
1863 }
1864 #endif /* FREEBSD */
1865
1866 /* All branches reach here on success (only). */
1867 tcp->u_error = error;
1868 tcp->u_rval = rval;
1869 return 0;
1870 }
1871
1872 static int
syscall_enter(tcp)1873 syscall_enter(tcp)
1874 struct tcb *tcp;
1875 {
1876 #ifndef USE_PROCFS
1877 int pid = tcp->pid;
1878 #endif /* !USE_PROCFS */
1879 #ifdef LINUX
1880 #if defined(S390) || defined(S390X)
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 if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
1889 return -1;
1890 }
1891 }
1892 #elif defined (ALPHA)
1893 {
1894 int i;
1895 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1896 tcp->u_nargs = sysent[tcp->scno].nargs;
1897 else
1898 tcp->u_nargs = MAX_ARGS;
1899 for (i = 0; i < tcp->u_nargs; i++) {
1900 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1901 * for scno somewhere above here!
1902 */
1903 if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1904 return -1;
1905 }
1906 }
1907 #elif defined (IA64)
1908 {
1909 if (!ia32) {
1910 unsigned long *out0, *rbs_end, cfm, sof, sol, i;
1911 /* be backwards compatible with kernel < 2.4.4... */
1912 # ifndef PT_RBS_END
1913 # define PT_RBS_END PT_AR_BSP
1914 # endif
1915
1916 if (upeek(pid, PT_RBS_END, (long *) &rbs_end) < 0)
1917 return -1;
1918 if (upeek(pid, PT_CFM, (long *) &cfm) < 0)
1919 return -1;
1920
1921 sof = (cfm >> 0) & 0x7f;
1922 sol = (cfm >> 7) & 0x7f;
1923 out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
1924
1925 if (tcp->scno >= 0 && tcp->scno < nsyscalls
1926 && sysent[tcp->scno].nargs != -1)
1927 tcp->u_nargs = sysent[tcp->scno].nargs;
1928 else
1929 tcp->u_nargs = MAX_ARGS;
1930 for (i = 0; i < tcp->u_nargs; ++i) {
1931 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1932 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1933 return -1;
1934 }
1935 } else {
1936 int i;
1937
1938 if (/* EBX = out0 */
1939 upeek(pid, PT_R11, (long *) &tcp->u_arg[0]) < 0
1940 /* ECX = out1 */
1941 || upeek(pid, PT_R9, (long *) &tcp->u_arg[1]) < 0
1942 /* EDX = out2 */
1943 || upeek(pid, PT_R10, (long *) &tcp->u_arg[2]) < 0
1944 /* ESI = out3 */
1945 || upeek(pid, PT_R14, (long *) &tcp->u_arg[3]) < 0
1946 /* EDI = out4 */
1947 || upeek(pid, PT_R15, (long *) &tcp->u_arg[4]) < 0
1948 /* EBP = out5 */
1949 || upeek(pid, PT_R13, (long *) &tcp->u_arg[5]) < 0)
1950 return -1;
1951
1952 for (i = 0; i < 6; ++i)
1953 /* truncate away IVE sign-extension */
1954 tcp->u_arg[i] &= 0xffffffff;
1955
1956 if (tcp->scno >= 0 && tcp->scno < nsyscalls
1957 && sysent[tcp->scno].nargs != -1)
1958 tcp->u_nargs = sysent[tcp->scno].nargs;
1959 else
1960 tcp->u_nargs = 5;
1961 }
1962 }
1963 #elif defined (MIPS)
1964 {
1965 long sp;
1966 int i, nargs;
1967
1968 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1969 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
1970 else
1971 nargs = tcp->u_nargs = MAX_ARGS;
1972 if(nargs > 4) {
1973 if(upeek(pid, REG_SP, &sp) < 0)
1974 return -1;
1975 for(i = 0; i < 4; i++) {
1976 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
1977 return -1;
1978 }
1979 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
1980 (char *)(tcp->u_arg + 4));
1981 } else {
1982 for(i = 0; i < nargs; i++) {
1983 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
1984 return -1;
1985 }
1986 }
1987 }
1988 #elif defined (POWERPC)
1989 #ifndef PT_ORIG_R3
1990 #define PT_ORIG_R3 34
1991 #endif
1992 {
1993 int i;
1994 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1995 tcp->u_nargs = sysent[tcp->scno].nargs;
1996 else
1997 tcp->u_nargs = MAX_ARGS;
1998 for (i = 0; i < tcp->u_nargs; i++) {
1999 if (upeek(pid, (i==0) ?
2000 (sizeof(unsigned long)*PT_ORIG_R3) :
2001 ((i+PT_R3)*sizeof(unsigned long)),
2002 &tcp->u_arg[i]) < 0)
2003 return -1;
2004 }
2005 }
2006 #elif defined (SPARC) || defined (SPARC64)
2007 {
2008 int i;
2009
2010 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2011 tcp->u_nargs = sysent[tcp->scno].nargs;
2012 else
2013 tcp->u_nargs = MAX_ARGS;
2014 for (i = 0; i < tcp->u_nargs; i++)
2015 tcp->u_arg[i] = *((®s.r_o0) + i);
2016 }
2017 #elif defined (HPPA)
2018 {
2019 int i;
2020
2021 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2022 tcp->u_nargs = sysent[tcp->scno].nargs;
2023 else
2024 tcp->u_nargs = MAX_ARGS;
2025 for (i = 0; i < tcp->u_nargs; i++) {
2026 if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
2027 return -1;
2028 }
2029 }
2030 #elif defined(ARM)
2031 {
2032 int i;
2033
2034 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2035 tcp->u_nargs = sysent[tcp->scno].nargs;
2036 else
2037 tcp->u_nargs = MAX_ARGS;
2038 for (i = 0; i < tcp->u_nargs; i++)
2039 tcp->u_arg[i] = regs.uregs[i];
2040 }
2041 #elif defined(SH)
2042 {
2043 int i;
2044 static int syscall_regs[] = {
2045 REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2046 REG_REG0, REG_REG0+1, REG_REG0+2
2047 };
2048
2049 tcp->u_nargs = sysent[tcp->scno].nargs;
2050 for (i = 0; i < tcp->u_nargs; i++) {
2051 if (upeek(pid, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2052 return -1;
2053 }
2054 }
2055 #elif defined(SH64)
2056 {
2057 int i;
2058 /* Registers used by SH5 Linux system calls for parameters */
2059 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2060
2061 /*
2062 * TODO: should also check that the number of arguments encoded
2063 * in the trap number matches the number strace expects.
2064 */
2065 /*
2066 assert(sysent[tcp->scno].nargs <
2067 sizeof(syscall_regs)/sizeof(syscall_regs[0]));
2068 */
2069
2070 tcp->u_nargs = sysent[tcp->scno].nargs;
2071 for (i = 0; i < tcp->u_nargs; i++) {
2072 if (upeek(pid, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2073 return -1;
2074 }
2075 }
2076
2077 #elif defined(X86_64)
2078 {
2079 int i;
2080 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2081 {RDI,RSI,RDX,R10,R8,R9}, /* x86-64 ABI */
2082 {RBX,RCX,RDX,RSI,RDI,RBP} /* i386 ABI */
2083 };
2084
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, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
2091 return -1;
2092 }
2093 }
2094 #else /* Other architecture (like i386) (32bits specific) */
2095 {
2096 int i;
2097 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2098 tcp->u_nargs = sysent[tcp->scno].nargs;
2099 else
2100 tcp->u_nargs = MAX_ARGS;
2101 for (i = 0; i < tcp->u_nargs; i++) {
2102 if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
2103 return -1;
2104 }
2105 }
2106 #endif
2107 #endif /* LINUX */
2108 #ifdef SUNOS4
2109 {
2110 int i;
2111 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2112 tcp->u_nargs = sysent[tcp->scno].nargs;
2113 else
2114 tcp->u_nargs = MAX_ARGS;
2115 for (i = 0; i < tcp->u_nargs; i++) {
2116 struct user *u;
2117
2118 if (upeek(pid, uoff(u_arg[0]) +
2119 (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2120 return -1;
2121 }
2122 }
2123 #endif /* SUNOS4 */
2124 #ifdef SVR4
2125 #ifdef MIPS
2126 /*
2127 * SGI is broken: even though it has pr_sysarg, it doesn't
2128 * set them on system call entry. Get a clue.
2129 */
2130 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2131 tcp->u_nargs = sysent[tcp->scno].nargs;
2132 else
2133 tcp->u_nargs = tcp->status.pr_nsysarg;
2134 if (tcp->u_nargs > 4) {
2135 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2136 4*sizeof(tcp->u_arg[0]));
2137 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2138 (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2139 }
2140 else {
2141 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2142 tcp->u_nargs*sizeof(tcp->u_arg[0]));
2143 }
2144 #elif UNIXWARE >= 2
2145 /*
2146 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2147 */
2148 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2149 tcp->u_nargs = sysent[tcp->scno].nargs;
2150 else
2151 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2152 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2153 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2154 #elif defined (HAVE_PR_SYSCALL)
2155 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2156 tcp->u_nargs = sysent[tcp->scno].nargs;
2157 else
2158 tcp->u_nargs = tcp->status.pr_nsysarg;
2159 {
2160 int i;
2161 for (i = 0; i < tcp->u_nargs; i++)
2162 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2163 }
2164 #elif defined (I386)
2165 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2166 tcp->u_nargs = sysent[tcp->scno].nargs;
2167 else
2168 tcp->u_nargs = 5;
2169 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2170 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2171 #else
2172 I DONT KNOW WHAT TO DO
2173 #endif /* !HAVE_PR_SYSCALL */
2174 #endif /* SVR4 */
2175 #ifdef FREEBSD
2176 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2177 sysent[tcp->scno].nargs > tcp->status.val)
2178 tcp->u_nargs = sysent[tcp->scno].nargs;
2179 else
2180 tcp->u_nargs = tcp->status.val;
2181 if (tcp->u_nargs < 0)
2182 tcp->u_nargs = 0;
2183 if (tcp->u_nargs > MAX_ARGS)
2184 tcp->u_nargs = MAX_ARGS;
2185 switch(regs.r_eax) {
2186 case SYS___syscall:
2187 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2188 regs.r_esp + sizeof(int) + sizeof(quad_t));
2189 break;
2190 case SYS_syscall:
2191 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2192 regs.r_esp + 2 * sizeof(int));
2193 break;
2194 default:
2195 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2196 regs.r_esp + sizeof(int));
2197 break;
2198 }
2199 #endif /* FREEBSD */
2200 return 1;
2201 }
2202
2203 int
trace_syscall(tcp)2204 trace_syscall(tcp)
2205 struct tcb *tcp;
2206 {
2207 int sys_res;
2208 struct timeval tv;
2209 int res;
2210
2211 /* Measure the exit time as early as possible to avoid errors. */
2212 if (dtime && (tcp->flags & TCB_INSYSCALL))
2213 gettimeofday(&tv, NULL);
2214
2215 res = get_scno(tcp);
2216 if (res != 1)
2217 return res;
2218
2219 res = syscall_fixup(tcp);
2220 if (res != 1)
2221 return res;
2222
2223 if (tcp->flags & TCB_INSYSCALL) {
2224 long u_error;
2225 res = get_error(tcp);
2226 if (res != 1)
2227 return res;
2228
2229 internal_syscall(tcp);
2230 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2231 !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2232 tcp->flags &= ~TCB_INSYSCALL;
2233 return 0;
2234 }
2235
2236 if (tcp->flags & TCB_REPRINT) {
2237 printleader(tcp);
2238 tprintf("<... ");
2239 if (tcp->scno >= nsyscalls || tcp->scno < 0)
2240 tprintf("syscall_%lu", tcp->scno);
2241 else
2242 tprintf("%s", sysent[tcp->scno].sys_name);
2243 tprintf(" resumed> ");
2244 }
2245
2246 if (cflag && tcp->scno < nsyscalls && tcp->scno >= 0) {
2247 if (counts == NULL) {
2248 counts = calloc(sizeof *counts, nsyscalls);
2249 if (counts == NULL) {
2250 fprintf(stderr, "\
2251 strace: out of memory for call counts\n");
2252 exit(1);
2253 }
2254 }
2255
2256 counts[tcp->scno].calls++;
2257 if (tcp->u_error)
2258 counts[tcp->scno].errors++;
2259 tv_sub(&tv, &tv, &tcp->etime);
2260 #ifndef HAVE_ANDROID_OS
2261 #ifdef LINUX
2262 if (tv_cmp(&tv, &tcp->dtime) > 0) {
2263 static struct timeval one_tick;
2264 if (one_tick.tv_usec == 0) {
2265 /* Initialize it. */
2266 struct itimerval it;
2267 memset(&it, 0, sizeof it);
2268 it.it_interval.tv_usec = 1;
2269 setitimer(ITIMER_REAL, &it, NULL);
2270 getitimer(ITIMER_REAL, &it);
2271 one_tick = it.it_interval;
2272 }
2273
2274 if (tv_nz(&tcp->dtime))
2275 tv = tcp->dtime;
2276 else if (tv_cmp(&tv, &one_tick) > 0) {
2277 if (tv_cmp(&shortest, &one_tick) < 0)
2278 tv = shortest;
2279 else
2280 tv = one_tick;
2281 }
2282 }
2283 #endif /* LINUX */
2284 #endif
2285 if (tv_cmp(&tv, &shortest) < 0)
2286 shortest = tv;
2287 tv_add(&counts[tcp->scno].time,
2288 &counts[tcp->scno].time, &tv);
2289 tcp->flags &= ~TCB_INSYSCALL;
2290 return 0;
2291 }
2292
2293 if (tcp->scno >= nsyscalls || tcp->scno < 0
2294 || (qual_flags[tcp->scno] & QUAL_RAW))
2295 sys_res = printargs(tcp);
2296 else {
2297 if (not_failing_only && tcp->u_error)
2298 return 0; /* ignore failed syscalls */
2299 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2300 }
2301 u_error = tcp->u_error;
2302 tprintf(") ");
2303 tabto(acolumn);
2304 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2305 qual_flags[tcp->scno] & QUAL_RAW) {
2306 if (u_error)
2307 tprintf("= -1 (errno %ld)", u_error);
2308 else
2309 tprintf("= %#lx", tcp->u_rval);
2310 }
2311 else if (!(sys_res & RVAL_NONE) && u_error) {
2312 switch (u_error) {
2313 #ifdef LINUX
2314 case ERESTARTSYS:
2315 tprintf("= ? ERESTARTSYS (To be restarted)");
2316 break;
2317 case ERESTARTNOINTR:
2318 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2319 break;
2320 case ERESTARTNOHAND:
2321 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2322 break;
2323 case ERESTART_RESTARTBLOCK:
2324 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2325 break;
2326 #endif /* LINUX */
2327 default:
2328 tprintf("= -1 ");
2329 if (u_error < 0)
2330 tprintf("E??? (errno %ld)", u_error);
2331 else if (u_error < nerrnos)
2332 tprintf("%s (%s)", errnoent[u_error],
2333 strerror(u_error));
2334 else
2335 tprintf("ERRNO_%ld (%s)", u_error,
2336 strerror(u_error));
2337 break;
2338 }
2339 }
2340 else {
2341 if (sys_res & RVAL_NONE)
2342 tprintf("= ?");
2343 else {
2344 switch (sys_res & RVAL_MASK) {
2345 case RVAL_HEX:
2346 tprintf("= %#lx", tcp->u_rval);
2347 break;
2348 case RVAL_OCTAL:
2349 tprintf("= %#lo", tcp->u_rval);
2350 break;
2351 case RVAL_UDECIMAL:
2352 tprintf("= %lu", tcp->u_rval);
2353 break;
2354 case RVAL_DECIMAL:
2355 tprintf("= %ld", tcp->u_rval);
2356 break;
2357 #ifdef HAVE_LONG_LONG
2358 case RVAL_LHEX:
2359 tprintf("= %#llx", tcp->u_lrval);
2360 break;
2361 case RVAL_LOCTAL:
2362 tprintf("= %#llo", tcp->u_lrval);
2363 break;
2364 case RVAL_LUDECIMAL:
2365 tprintf("= %llu", tcp->u_lrval);
2366 break;
2367 case RVAL_LDECIMAL:
2368 tprintf("= %lld", tcp->u_lrval);
2369 break;
2370 #endif
2371 default:
2372 fprintf(stderr,
2373 "invalid rval format\n");
2374 break;
2375 }
2376 }
2377 if ((sys_res & RVAL_STR) && tcp->auxstr)
2378 tprintf(" (%s)", tcp->auxstr);
2379 }
2380 if (dtime) {
2381 tv_sub(&tv, &tv, &tcp->etime);
2382 tprintf(" <%ld.%06ld>",
2383 (long) tv.tv_sec, (long) tv.tv_usec);
2384 }
2385 printtrailer(tcp);
2386
2387 dumpio(tcp);
2388 if (fflush(tcp->outf) == EOF)
2389 return -1;
2390 tcp->flags &= ~TCB_INSYSCALL;
2391 return 0;
2392 }
2393
2394 /* Entering system call */
2395 res = syscall_enter(tcp);
2396 if (res != 1)
2397 return res;
2398
2399 switch (known_scno(tcp)) {
2400 #ifdef LINUX
2401 #if !defined (ALPHA) && !defined(SPARC) && !defined(SPARC64) && !defined(MIPS) && !defined(HPPA) && !defined(__ARM_EABI__) //ANDROID
2402 case SYS_socketcall:
2403 decode_subcall(tcp, SYS_socket_subcall,
2404 SYS_socket_nsubcalls, deref_style);
2405 break;
2406 case SYS_ipc:
2407 decode_subcall(tcp, SYS_ipc_subcall,
2408 SYS_ipc_nsubcalls, shift_style);
2409 break;
2410 #endif /* !ALPHA && !MIPS && !SPARC && !SPARC64 && !HPPA */
2411 #if defined (SPARC) || defined (SPARC64)
2412 case SYS_socketcall:
2413 sparc_socket_decode (tcp);
2414 break;
2415 #endif
2416 #endif /* LINUX */
2417 #ifdef SVR4
2418 #ifdef SYS_pgrpsys_subcall
2419 case SYS_pgrpsys:
2420 decode_subcall(tcp, SYS_pgrpsys_subcall,
2421 SYS_pgrpsys_nsubcalls, shift_style);
2422 break;
2423 #endif /* SYS_pgrpsys_subcall */
2424 #ifdef SYS_sigcall_subcall
2425 case SYS_sigcall:
2426 decode_subcall(tcp, SYS_sigcall_subcall,
2427 SYS_sigcall_nsubcalls, mask_style);
2428 break;
2429 #endif /* SYS_sigcall_subcall */
2430 case SYS_msgsys:
2431 decode_subcall(tcp, SYS_msgsys_subcall,
2432 SYS_msgsys_nsubcalls, shift_style);
2433 break;
2434 case SYS_shmsys:
2435 decode_subcall(tcp, SYS_shmsys_subcall,
2436 SYS_shmsys_nsubcalls, shift_style);
2437 break;
2438 case SYS_semsys:
2439 decode_subcall(tcp, SYS_semsys_subcall,
2440 SYS_semsys_nsubcalls, shift_style);
2441 break;
2442 #if 0 /* broken */
2443 case SYS_utssys:
2444 decode_subcall(tcp, SYS_utssys_subcall,
2445 SYS_utssys_nsubcalls, shift_style);
2446 break;
2447 #endif
2448 case SYS_sysfs:
2449 decode_subcall(tcp, SYS_sysfs_subcall,
2450 SYS_sysfs_nsubcalls, shift_style);
2451 break;
2452 case SYS_spcall:
2453 decode_subcall(tcp, SYS_spcall_subcall,
2454 SYS_spcall_nsubcalls, shift_style);
2455 break;
2456 #ifdef SYS_context_subcall
2457 case SYS_context:
2458 decode_subcall(tcp, SYS_context_subcall,
2459 SYS_context_nsubcalls, shift_style);
2460 break;
2461 #endif /* SYS_context_subcall */
2462 #ifdef SYS_door_subcall
2463 case SYS_door:
2464 decode_subcall(tcp, SYS_door_subcall,
2465 SYS_door_nsubcalls, door_style);
2466 break;
2467 #endif /* SYS_door_subcall */
2468 #ifdef SYS_kaio_subcall
2469 case SYS_kaio:
2470 decode_subcall(tcp, SYS_kaio_subcall,
2471 SYS_kaio_nsubcalls, shift_style);
2472 break;
2473 #endif
2474 #endif /* SVR4 */
2475 #ifdef FREEBSD
2476 case SYS_msgsys:
2477 case SYS_shmsys:
2478 case SYS_semsys:
2479 decode_subcall(tcp, 0, 0, table_style);
2480 break;
2481 #endif
2482 #ifdef SUNOS4
2483 case SYS_semsys:
2484 decode_subcall(tcp, SYS_semsys_subcall,
2485 SYS_semsys_nsubcalls, shift_style);
2486 break;
2487 case SYS_msgsys:
2488 decode_subcall(tcp, SYS_msgsys_subcall,
2489 SYS_msgsys_nsubcalls, shift_style);
2490 break;
2491 case SYS_shmsys:
2492 decode_subcall(tcp, SYS_shmsys_subcall,
2493 SYS_shmsys_nsubcalls, shift_style);
2494 break;
2495 #endif
2496 }
2497
2498 internal_syscall(tcp);
2499 if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2500 tcp->flags |= TCB_INSYSCALL;
2501 return 0;
2502 }
2503
2504 if (cflag) {
2505 gettimeofday(&tcp->etime, NULL);
2506 tcp->flags |= TCB_INSYSCALL;
2507 return 0;
2508 }
2509
2510 printleader(tcp);
2511 tcp->flags &= ~TCB_REPRINT;
2512 tcp_last = tcp;
2513 if (tcp->scno >= nsyscalls || tcp->scno < 0)
2514 tprintf("syscall_%lu(", tcp->scno);
2515 else
2516 tprintf("%s(", sysent[tcp->scno].sys_name);
2517 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2518 ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2519 sys_res = printargs(tcp);
2520 else
2521 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2522 if (fflush(tcp->outf) == EOF)
2523 return -1;
2524 tcp->flags |= TCB_INSYSCALL;
2525 /* Measure the entrance time as late as possible to avoid errors. */
2526 if (dtime)
2527 gettimeofday(&tcp->etime, NULL);
2528 return sys_res;
2529 }
2530
2531 int
printargs(tcp)2532 printargs(tcp)
2533 struct tcb *tcp;
2534 {
2535 if (entering(tcp)) {
2536 int i;
2537
2538 for (i = 0; i < tcp->u_nargs; i++)
2539 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2540 }
2541 return 0;
2542 }
2543
2544 long
getrval2(tcp)2545 getrval2(tcp)
2546 struct tcb *tcp;
2547 {
2548 long val = -1;
2549
2550 #ifdef LINUX
2551 #if defined (SPARC) || defined (SPARC64)
2552 struct regs regs;
2553 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
2554 return -1;
2555 val = regs.r_o1;
2556 #elif defined(SH)
2557 if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
2558 return -1;
2559 #elif defined(IA64)
2560 if (upeek(tcp->pid, PT_R9, &val) < 0)
2561 return -1;
2562 #endif /* SPARC || SPARC64 */
2563 #endif /* LINUX */
2564
2565 #ifdef SUNOS4
2566 if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
2567 return -1;
2568 #endif /* SUNOS4 */
2569
2570 #ifdef SVR4
2571 #ifdef SPARC
2572 val = tcp->status.PR_REG[R_O1];
2573 #endif /* SPARC */
2574 #ifdef I386
2575 val = tcp->status.PR_REG[EDX];
2576 #endif /* I386 */
2577 #ifdef X86_64
2578 val = tcp->status.PR_REG[RDX];
2579 #endif /* X86_64 */
2580 #ifdef MIPS
2581 val = tcp->status.PR_REG[CTX_V1];
2582 #endif /* MIPS */
2583 #endif /* SVR4 */
2584 #ifdef FREEBSD
2585 struct reg regs;
2586 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
2587 val = regs.r_edx;
2588 #endif
2589 return val;
2590 }
2591
2592 /*
2593 * Apparently, indirect system calls have already be converted by ptrace(2),
2594 * so if you see "indir" this program has gone astray.
2595 */
2596 int
sys_indir(tcp)2597 sys_indir(tcp)
2598 struct tcb *tcp;
2599 {
2600 int i, scno, nargs;
2601
2602 if (entering(tcp)) {
2603 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2604 fprintf(stderr, "Bogus syscall: %u\n", scno);
2605 return 0;
2606 }
2607 nargs = sysent[scno].nargs;
2608 tprintf("%s", sysent[scno].sys_name);
2609 for (i = 0; i < nargs; i++)
2610 tprintf(", %#lx", tcp->u_arg[i+1]);
2611 }
2612 return 0;
2613 }
2614
2615 static int
time_cmp(a,b)2616 time_cmp(a, b)
2617 void *a;
2618 void *b;
2619 {
2620 return -tv_cmp(&counts[*((int *) a)].time, &counts[*((int *) b)].time);
2621 }
2622
2623 static int
syscall_cmp(a,b)2624 syscall_cmp(a, b)
2625 void *a;
2626 void *b;
2627 {
2628 return strcmp(sysent[*((int *) a)].sys_name,
2629 sysent[*((int *) b)].sys_name);
2630 }
2631
2632 static int
count_cmp(a,b)2633 count_cmp(a, b)
2634 void *a;
2635 void *b;
2636 {
2637 int m = counts[*((int *) a)].calls, n = counts[*((int *) b)].calls;
2638
2639 return (m < n) ? 1 : (m > n) ? -1 : 0;
2640 }
2641
2642 static int (*sortfun)();
2643 static struct timeval overhead = { -1, -1 };
2644
2645 void
set_sortby(sortby)2646 set_sortby(sortby)
2647 char *sortby;
2648 {
2649 if (strcmp(sortby, "time") == 0)
2650 sortfun = time_cmp;
2651 else if (strcmp(sortby, "calls") == 0)
2652 sortfun = count_cmp;
2653 else if (strcmp(sortby, "name") == 0)
2654 sortfun = syscall_cmp;
2655 else if (strcmp(sortby, "nothing") == 0)
2656 sortfun = NULL;
2657 else {
2658 fprintf(stderr, "invalid sortby: `%s'\n", sortby);
2659 exit(1);
2660 }
2661 }
2662
set_overhead(n)2663 void set_overhead(n)
2664 int n;
2665 {
2666 overhead.tv_sec = n / 1000000;
2667 overhead.tv_usec = n % 1000000;
2668 }
2669
2670 void
call_summary(outf)2671 call_summary(outf)
2672 FILE *outf;
2673 {
2674 int i, j;
2675 int call_cum, error_cum;
2676 struct timeval tv_cum, dtv;
2677 double percent;
2678 char *dashes = "-------------------------";
2679 char error_str[16];
2680
2681 int *sorted_count = malloc(nsyscalls * sizeof(int));
2682
2683 call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
2684 if (overhead.tv_sec == -1) {
2685 tv_mul(&overhead, &shortest, 8);
2686 tv_div(&overhead, &overhead, 10);
2687 }
2688 for (i = 0; i < nsyscalls; i++) {
2689 sorted_count[i] = i;
2690 if (counts == NULL || counts[i].calls == 0)
2691 continue;
2692 tv_mul(&dtv, &overhead, counts[i].calls);
2693 tv_sub(&counts[i].time, &counts[i].time, &dtv);
2694 call_cum += counts[i].calls;
2695 error_cum += counts[i].errors;
2696 tv_add(&tv_cum, &tv_cum, &counts[i].time);
2697 }
2698 if (counts && sortfun)
2699 qsort((void *) sorted_count, nsyscalls, sizeof(int), sortfun);
2700 fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",
2701 "% time", "seconds", "usecs/call",
2702 "calls", "errors", "syscall");
2703 fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2704 dashes, dashes, dashes, dashes, dashes, dashes);
2705 if (counts) {
2706 for (i = 0; i < nsyscalls; i++) {
2707 j = sorted_count[i];
2708 if (counts[j].calls == 0)
2709 continue;
2710 tv_div(&dtv, &counts[j].time, counts[j].calls);
2711 if (counts[j].errors)
2712 sprintf(error_str, "%d", counts[j].errors);
2713 else
2714 error_str[0] = '\0';
2715 percent = (100.0 * tv_float(&counts[j].time)
2716 / tv_float(&tv_cum));
2717 fprintf(outf, "%6.2f %4ld.%06ld %11ld %9d %9.9s %s\n",
2718 percent, (long) counts[j].time.tv_sec,
2719 (long) counts[j].time.tv_usec,
2720 (long) 1000000 * dtv.tv_sec + dtv.tv_usec,
2721 counts[j].calls,
2722 error_str, sysent[j].sys_name);
2723 }
2724 }
2725 free(sorted_count);
2726
2727 fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2728 dashes, dashes, dashes, dashes, dashes, dashes);
2729 if (error_cum)
2730 sprintf(error_str, "%d", error_cum);
2731 else
2732 error_str[0] = '\0';
2733 fprintf(outf, "%6.6s %4ld.%06ld %11.11s %9d %9.9s %s\n",
2734 "100.00", (long) tv_cum.tv_sec, (long) tv_cum.tv_usec, "",
2735 call_cum, error_str, "total");
2736
2737 }
2738