1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl> 6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation 7 * Linux for s390 port by D.J. Barrow 8 * <barrow_dj (at) mail.yahoo.com,djbarrow (at) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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