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