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>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
42 #include <sys/syscall.h>
43 #include <sys/param.h>
46 #if defined (SPARC) || defined (SPARC64)
47 # define fpq kernel_fpq
49 # define fpu kernel_fpu
52 #if defined (SPARC) || defined (SPARC64)
61 #ifndef PTRACE_PEEKUSR
62 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
64 #elif defined(HAVE_LINUX_PTRACE_H)
66 # ifdef HAVE_STRUCT_IA64_FPREG
67 # define ia64_fpreg XXX_ia64_fpreg
69 # ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70 # define pt_all_user_regs XXX_pt_all_user_regs
72 #include <linux/ptrace.h>
74 # undef pt_all_user_regs
77 #if defined (LINUX) && defined (SPARC64)
79 # undef PTRACE_GETREGS
80 # define PTRACE_GETREGS PTRACE_GETREGS64
81 # undef PTRACE_SETREGS
82 # define PTRACE_SETREGS PTRACE_SETREGS64
83 #endif /* LINUX && SPARC64 */
85 #if defined(LINUX) && defined(IA64)
86 # include <asm/ptrace_offsets.h>
90 #define NR_SYSCALL_BASE 0
93 #define ERESTARTSYS 512
95 #ifndef ERESTARTNOINTR
96 #define ERESTARTNOINTR 513
98 #ifndef ERESTARTNOHAND
99 #define ERESTARTNOHAND 514 /* restart if no handler.. */
102 #define ENOIOCTLCMD 515 /* No ioctl command */
104 #ifndef ERESTART_RESTARTBLOCK
105 #define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
113 #undef NR_SYSCALL_BASE
114 #define NR_SYSCALL_BASE __NR_SYSCALL_BASE
120 /* Define these shorthand notations to simplify the syscallent files. */
121 #define TD TRACE_DESC
122 #define TF TRACE_FILE
124 #define TN TRACE_NETWORK
125 #define TP TRACE_PROCESS
126 #define TS TRACE_SIGNAL
128 static const struct sysent sysent0[] = {
129 #include "syscallent.h"
131 static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
132 int qual_flags0[MAX_QUALS];
134 #if SUPPORTED_PERSONALITIES >= 2
135 static const struct sysent sysent1[] = {
136 #include "syscallent1.h"
138 static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
139 int qual_flags1[MAX_QUALS];
140 #endif /* SUPPORTED_PERSONALITIES >= 2 */
142 #if SUPPORTED_PERSONALITIES >= 3
143 static const struct sysent sysent2[] = {
144 #include "syscallent2.h"
146 static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
147 int qual_flags2[MAX_QUALS];
148 #endif /* SUPPORTED_PERSONALITIES >= 3 */
150 const struct sysent *sysent;
154 /* Now undef them since short defines cause wicked namespace pollution. */
162 static const char *const errnoent0[] = {
163 #include "errnoent.h"
165 static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
167 #if SUPPORTED_PERSONALITIES >= 2
168 static const char *const errnoent1[] = {
169 #include "errnoent1.h"
171 static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
172 #endif /* SUPPORTED_PERSONALITIES >= 2 */
174 #if SUPPORTED_PERSONALITIES >= 3
175 static const char *const errnoent2[] = {
176 #include "errnoent2.h"
178 static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
179 #endif /* SUPPORTED_PERSONALITIES >= 3 */
181 const char *const *errnoent;
184 int current_personality;
186 #ifndef PERSONALITY0_WORDSIZE
187 # define PERSONALITY0_WORDSIZE sizeof(long)
189 const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
190 PERSONALITY0_WORDSIZE,
191 #if SUPPORTED_PERSONALITIES > 1
192 PERSONALITY1_WORDSIZE,
194 #if SUPPORTED_PERSONALITIES > 2
195 PERSONALITY2_WORDSIZE,
200 set_personality(personality)
203 switch (personality) {
205 errnoent = errnoent0;
208 nsyscalls = nsyscalls0;
209 ioctlent = ioctlent0;
210 nioctlents = nioctlents0;
211 signalent = signalent0;
212 nsignals = nsignals0;
213 qual_flags = qual_flags0;
216 #if SUPPORTED_PERSONALITIES >= 2
218 errnoent = errnoent1;
221 nsyscalls = nsyscalls1;
222 ioctlent = ioctlent1;
223 nioctlents = nioctlents1;
224 signalent = signalent1;
225 nsignals = nsignals1;
226 qual_flags = qual_flags1;
228 #endif /* SUPPORTED_PERSONALITIES >= 2 */
230 #if SUPPORTED_PERSONALITIES >= 3
232 errnoent = errnoent2;
235 nsyscalls = nsyscalls2;
236 ioctlent = ioctlent2;
237 nioctlents = nioctlents2;
238 signalent = signalent2;
239 nsignals = nsignals2;
240 qual_flags = qual_flags2;
242 #endif /* SUPPORTED_PERSONALITIES >= 3 */
248 current_personality = personality;
258 static struct call_counts *counts;
260 static struct timeval shortest = { 1000000, 0 };
262 static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
264 static const struct qual_options {
270 { QUAL_TRACE, "trace", qual_syscall, "system call" },
271 { QUAL_TRACE, "t", qual_syscall, "system call" },
272 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
273 { QUAL_ABBREV, "a", qual_syscall, "system call" },
274 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
275 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
276 { QUAL_RAW, "raw", qual_syscall, "system call" },
277 { QUAL_RAW, "x", qual_syscall, "system call" },
278 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
279 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
280 { QUAL_SIGNAL, "s", qual_signal, "signal" },
281 { QUAL_FAULT, "fault", qual_fault, "fault" },
282 { QUAL_FAULT, "faults", qual_fault, "fault" },
283 { QUAL_FAULT, "m", qual_fault, "fault" },
284 { QUAL_READ, "read", qual_desc, "descriptor" },
285 { QUAL_READ, "reads", qual_desc, "descriptor" },
286 { QUAL_READ, "r", qual_desc, "descriptor" },
287 { QUAL_WRITE, "write", qual_desc, "descriptor" },
288 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
289 { QUAL_WRITE, "w", qual_desc, "descriptor" },
290 { 0, NULL, NULL, NULL },
294 qualify_one(n, opt, not, pers)
296 const struct qual_options *opt;
300 if (pers == 0 || pers < 0) {
302 qual_flags0[n] &= ~opt->bitflag;
304 qual_flags0[n] |= opt->bitflag;
307 #if SUPPORTED_PERSONALITIES >= 2
308 if (pers == 1 || pers < 0) {
310 qual_flags1[n] &= ~opt->bitflag;
312 qual_flags1[n] |= opt->bitflag;
314 #endif /* SUPPORTED_PERSONALITIES >= 2 */
316 #if SUPPORTED_PERSONALITIES >= 3
317 if (pers == 2 || pers < 0) {
319 qual_flags2[n] &= ~opt->bitflag;
321 qual_flags2[n] |= opt->bitflag;
323 #endif /* SUPPORTED_PERSONALITIES >= 3 */
327 qual_syscall(s, opt, not)
329 const struct qual_options *opt;
335 if (isdigit((unsigned char)*s)) {
337 if (i < 0 || i >= nsyscalls)
339 qualify_one(i, opt, not, -1);
342 for (i = 0; i < nsyscalls; i++) {
343 if (strcmp(s, sysent0[i].sys_name) == 0) {
344 qualify_one(i, opt, not, 0);
348 #if SUPPORTED_PERSONALITIES >= 2
349 if (strcmp(s, sysent1[i].sys_name) == 0) {
350 qualify_one(i, opt, not, 1);
353 #endif /* SUPPORTED_PERSONALITIES >= 2 */
355 #if SUPPORTED_PERSONALITIES >= 3
356 if (strcmp(s, sysent2[i].sys_name) == 0) {
357 qualify_one(i, opt, not, 2);
360 #endif /* SUPPORTED_PERSONALITIES >= 3 */
366 qual_signal(s, opt, not)
368 const struct qual_options *opt;
374 if (isdigit((unsigned char)*s)) {
376 if (signo < 0 || signo >= MAX_QUALS)
378 qualify_one(signo, opt, not, -1);
381 if (strlen(s) >= sizeof buf)
385 for (i = 0; s[i]; i++)
386 s[i] = toupper((unsigned char)(s[i]));
387 if (strncmp(s, "SIG", 3) == 0)
389 for (i = 0; i <= NSIG; i++)
390 if (strcmp(s, signame(i) + 3) == 0) {
391 qualify_one(i, opt, not, -1);
398 qual_fault(s, opt, not)
400 const struct qual_options *opt;
407 qual_desc(s, opt, not)
409 const struct qual_options *opt;
412 if (isdigit((unsigned char)*s)) {
414 if (desc < 0 || desc >= MAX_QUALS)
416 qualify_one(desc, opt, not, -1);
426 if (strcmp(s, "file") == 0)
428 if (strcmp(s, "ipc") == 0)
430 if (strcmp(s, "network") == 0)
431 return TRACE_NETWORK;
432 if (strcmp(s, "process") == 0)
433 return TRACE_PROCESS;
434 if (strcmp(s, "signal") == 0)
436 if (strcmp(s, "desc") == 0)
445 const struct qual_options *opt;
450 opt = &qual_options[0];
451 for (i = 0; (p = qual_options[i].option_name); i++) {
453 if (strncmp(s, p, n) == 0 && s[n] == '=') {
454 opt = &qual_options[i];
464 if (strcmp(s, "none") == 0) {
468 if (strcmp(s, "all") == 0) {
469 for (i = 0; i < MAX_QUALS; i++) {
470 qualify_one(i, opt, not, -1);
474 for (i = 0; i < MAX_QUALS; i++) {
475 qualify_one(i, opt, !not, -1);
477 for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {
478 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
479 for (i = 0; i < MAX_QUALS; i++) {
480 if (sysent0[i].sys_flags & n)
481 qualify_one(i, opt, not, 0);
483 #if SUPPORTED_PERSONALITIES >= 2
484 if (sysent1[i].sys_flags & n)
485 qualify_one(i, opt, not, 1);
486 #endif /* SUPPORTED_PERSONALITIES >= 2 */
488 #if SUPPORTED_PERSONALITIES >= 3
489 if (sysent2[i].sys_flags & n)
490 qualify_one(i, opt, not, 2);
491 #endif /* SUPPORTED_PERSONALITIES >= 3 */
495 if (opt->qualify(p, opt, not)) {
496 fprintf(stderr, "strace: invalid %s `%s'\n",
497 opt->argument_name, p);
510 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
512 switch (known_scno(tcp)) {
517 #if defined SYS_pread && SYS_pread64 != SYS_pread
522 #elif defined SYS_sub_recv
527 #elif defined SYS_sub_recvfrom
528 case SYS_sub_recvfrom:
530 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
531 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
537 #if defined SYS_pwrite && SYS_pwrite64 != SYS_pwrite
542 #elif defined SYS_sub_send
547 #elif defined SYS_sub_sendto
550 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
551 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
555 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
556 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
562 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
563 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
570 enum subcall_style { shift_style, deref_style, mask_style, door_style };
572 enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
580 static const struct subcall subcalls_table[] = {
581 { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
583 { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
585 { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
587 { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
591 #if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) ))
593 static const int socket_map [] = {
596 /* SYS_CONNECT */ 98,
597 /* SYS_LISTEN */ 106,
599 /* SYS_GETSOCKNAME */ 150,
600 /* SYS_GETPEERNAME */ 141,
601 /* SYS_SOCKETPAIR */ 135,
604 /* SYS_SENDTO */ 133,
605 /* SYS_RECVFROM */ 125,
606 /* SYS_SHUTDOWN */ 134,
607 /* SYS_SETSOCKOPT */ 105,
608 /* SYS_GETSOCKOPT */ 118,
609 /* SYS_SENDMSG */ 114,
610 /* SYS_RECVMSG */ 113
613 #if defined (SPARC) || defined (SPARC64)
615 sparc_socket_decode (tcp)
621 if (tcp->u_arg [0] < 1 || tcp->u_arg [0] > sizeof(socket_map)/sizeof(int)+1){
624 tcp->scno = socket_map [tcp->u_arg [0]-1];
625 n = tcp->u_nargs = sysent [tcp->scno].nargs;
626 addr = tcp->u_arg [1];
627 for (i = 0; i < n; i++){
629 if (umoven (tcp, addr, sizeof (arg), (void *) &arg) < 0)
631 tcp->u_arg [i] = arg;
632 addr += sizeof (arg);
638 decode_subcall(tcp, subcall, nsubcalls, style)
642 enum subcall_style style;
644 unsigned long addr, mask;
646 int size = personality_wordsize[current_personality];
650 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
652 tcp->scno = subcall + tcp->u_arg[0];
653 if (sysent[tcp->scno].nargs != -1)
654 tcp->u_nargs = sysent[tcp->scno].nargs;
657 for (i = 0; i < tcp->u_nargs; i++)
658 tcp->u_arg[i] = tcp->u_arg[i + 1];
661 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
663 tcp->scno = subcall + tcp->u_arg[0];
664 addr = tcp->u_arg[1];
665 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
666 if (size == sizeof(int)) {
668 if (umove(tcp, addr, &arg) < 0)
672 else if (size == sizeof(long)) {
674 if (umove(tcp, addr, &arg) < 0)
682 tcp->u_nargs = sysent[tcp->scno].nargs;
685 mask = (tcp->u_arg[0] >> 8) & 0xff;
686 for (i = 0; mask; i++)
690 tcp->u_arg[0] &= 0xff;
691 tcp->scno = subcall + i;
692 if (sysent[tcp->scno].nargs != -1)
693 tcp->u_nargs = sysent[tcp->scno].nargs;
697 * Oh, yuck. The call code is the *sixth* argument.
698 * (don't you mean the *last* argument? - JH)
700 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
702 tcp->scno = subcall + tcp->u_arg[5];
703 if (sysent[tcp->scno].nargs != -1)
704 tcp->u_nargs = sysent[tcp->scno].nargs;
710 for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
711 if (subcalls_table[i].call == tcp->scno) break;
712 if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
713 tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
714 tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
715 for (i = 0; i < tcp->u_nargs; i++)
716 tcp->u_arg[i] = tcp->u_arg[i + 1];
724 struct tcb *tcp_last = NULL;
727 internal_syscall(tcp)
731 * We must always trace a few critical system calls in order to
732 * correctly support following forks in the presence of tracing
735 switch (known_scno(tcp)) {
796 internal_wait(tcp, 2);
800 internal_wait(tcp, 3);
810 #ifdef __NR_exit_group
811 case __NR_exit_group:
814 case 252: /* IA-32 __NR_exit_group */
829 #elif defined (POWERPC)
830 static long result,flags;
834 static struct pt_regs regs;
835 #elif defined (ALPHA)
838 #elif defined (SPARC) || defined (SPARC64)
839 static struct regs regs;
840 static unsigned long trap;
844 #elif defined(S390) || defined(S390X)
847 static long syscall_mode;
854 #elif defined(X86_64)
872 #if defined(S390) || defined(S390X)
873 if (tcp->flags & TCB_WAITEXECVE) {
875 * When the execve system call completes successfully, the
876 * new process still has -ENOSYS (old style) or __NR_execve
877 * (new style) in gpr2. We cannot recover the scno again
878 * by disassembly, because the image that executed the
879 * syscall is gone now. Fortunately, we don't want it. We
880 * leave the flag set so that syscall_fixup can fake the
883 if (tcp->flags & TCB_INSYSCALL)
886 * This is the SIGTRAP after execve. We cannot try to read
887 * the system call here either.
889 tcp->flags &= ~TCB_WAITEXECVE;
893 if (upeek(pid, PT_GPR2, &syscall_mode) < 0)
896 if (syscall_mode != -ENOSYS) {
898 * Since kernel version 2.5.44 the scno gets passed in gpr2.
903 * Old style of "passing" the scno via the SVC instruction.
906 long opcode, offset_reg, tmp;
908 int gpr_offset[16] = {PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
909 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
910 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
911 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15};
913 if (upeek(pid, PT_PSWADDR, &pc) < 0)
916 opcode = ptrace(PTRACE_PEEKTEXT, pid, (char *)(pc-sizeof(long)), 0);
918 perror("peektext(pc-oneword)");
923 * We have to check if the SVC got executed directly or via an
924 * EXECUTE instruction. In case of EXECUTE it is necessary to do
925 * instruction decoding to derive the system call number.
926 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
927 * so that this doesn't work if a SVC opcode is part of an EXECUTE
928 * opcode. Since there is no way to find out the opcode size this
929 * is the best we can do...
932 if ((opcode & 0xff00) == 0x0a00) {
934 scno = opcode & 0xff;
937 /* SVC got executed by EXECUTE instruction */
940 * Do instruction decoding of EXECUTE. If you really want to
941 * understand this, read the Principles of Operations.
943 svc_addr = (void *) (opcode & 0xfff);
946 offset_reg = (opcode & 0x000f0000) >> 16;
947 if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
952 offset_reg = (opcode & 0x0000f000) >> 12;
953 if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
957 scno = ptrace(PTRACE_PEEKTEXT, pid, svc_addr, 0);
966 offset_reg = (opcode & 0x00f00000) >> 20;
967 if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
970 scno = (scno | tmp) & 0xff;
973 #elif defined (POWERPC)
974 if (upeek(pid, sizeof(unsigned long)*PT_R0, &scno) < 0)
976 if (!(tcp->flags & TCB_INSYSCALL)) {
977 /* Check if we return from execve. */
978 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
979 tcp->flags &= ~TCB_WAITEXECVE;
984 if (upeek(pid, 4*ORIG_EAX, &scno) < 0)
986 #elif defined (X86_64)
987 if (upeek(pid, 8*ORIG_RAX, &scno) < 0)
990 if (!(tcp->flags & TCB_INSYSCALL)) {
991 static int currpers=-1;
994 /* Check CS register value. On x86-64 linux it is:
995 * 0x33 for long mode (64 bit)
996 * 0x23 for compatibility mode (32 bit)
997 * It takes only one ptrace and thus doesn't need
1000 if (upeek(pid, 8*CS, &val) < 0)
1004 case 0x23: currpers = 1; break;
1005 case 0x33: currpers = 0; break;
1007 fprintf(stderr, "Unknown value CS=0x%02X while "
1008 "detecting personality of process "
1009 "PID=%d\n", (int)val, pid);
1010 currpers = current_personality;
1014 /* This version analyzes the opcode of a syscall instruction.
1015 * (int 0x80 on i386 vs. syscall on x86-64)
1016 * It works, but is too complicated.
1018 unsigned long val, rip, i;
1020 if(upeek(pid, 8*RIP, &rip)<0)
1021 perror("upeek(RIP)");
1023 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1027 call = ptrace(PTRACE_PEEKTEXT,pid,(char *)rip,0);
1029 printf("ptrace_peektext failed: %s\n",
1031 switch (call & 0xffff)
1033 /* x86-64: syscall = 0x0f 0x05 */
1034 case 0x050f: currpers = 0; break;
1035 /* i386: int 0x80 = 0xcd 0x80 */
1036 case 0x80cd: currpers = 1; break;
1038 currpers = current_personality;
1040 "Unknown syscall opcode (0x%04X) while "
1041 "detecting personality of process "
1042 "PID=%d\n", (int)call, pid);
1046 if(currpers != current_personality)
1048 char *names[]={"64 bit", "32 bit"};
1049 set_personality(currpers);
1050 printf("[ Process PID=%d runs in %s mode. ]\n",
1051 pid, names[current_personality]);
1055 # define IA64_PSR_IS ((long)1 << 34)
1056 if (upeek (pid, PT_CR_IPSR, &psr) >= 0)
1057 ia32 = (psr & IA64_PSR_IS) != 0;
1058 if (!(tcp->flags & TCB_INSYSCALL)) {
1060 if (upeek(pid, PT_R1, &scno) < 0) /* orig eax */
1063 if (upeek (pid, PT_R15, &scno) < 0)
1066 /* Check if we return from execve. */
1067 if (tcp->flags & TCB_WAITEXECVE) {
1068 tcp->flags &= ~TCB_WAITEXECVE;
1072 /* syscall in progress */
1073 if (upeek (pid, PT_R8, &r8) < 0)
1075 if (upeek (pid, PT_R10, &r10) < 0)
1080 * Read complete register set in one go.
1082 if (ptrace(PTRACE_GETREGS, pid, NULL, (void *)®s) == -1)
1086 * We only need to grab the syscall number on syscall entry.
1088 if (regs.ARM_ip == 0) {
1090 * Note: we only deal with only 32-bit CPUs here.
1092 if (regs.ARM_cpsr & 0x20) {
1094 * Get the Thumb-mode system call number
1099 * Get the ARM-mode system call number
1102 scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
1106 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1107 tcp->flags &= ~TCB_WAITEXECVE;
1111 /* Handle the EABI syscall convention. We do not
1112 bother converting structures between the two
1113 ABIs, but basic functionality should work even
1114 if strace and the traced program have different
1116 if (scno == 0xef000000) {
1119 if ((scno & 0x0ff00000) != 0x0f900000) {
1120 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1126 * Fixup the syscall number
1132 if (tcp->flags & TCB_INSYSCALL) {
1133 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1134 tcp->flags &= ~TCB_INSYSCALL;
1137 if (!(tcp->flags & TCB_INSYSCALL)) {
1138 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1139 tcp->flags |= TCB_INSYSCALL;
1142 #elif defined (M68K)
1143 if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
1145 #elif defined (MIPS)
1146 if (upeek(pid, REG_A3, &a3) < 0)
1149 if(!(tcp->flags & TCB_INSYSCALL)) {
1150 if (upeek(pid, REG_V0, &scno) < 0)
1153 if (scno < 0 || scno > nsyscalls) {
1154 if(a3 == 0 || a3 == -1) {
1156 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1161 if (upeek(pid, REG_V0, &r2) < 0)
1164 #elif defined (ALPHA)
1165 if (upeek(pid, REG_A3, &a3) < 0)
1168 if (!(tcp->flags & TCB_INSYSCALL)) {
1169 if (upeek(pid, REG_R0, &scno) < 0)
1172 /* Check if we return from execve. */
1173 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1174 tcp->flags &= ~TCB_WAITEXECVE;
1179 * Do some sanity checks to figure out if it's
1180 * really a syscall entry
1182 if (scno < 0 || scno > nsyscalls) {
1183 if (a3 == 0 || a3 == -1) {
1185 fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1191 if (upeek(pid, REG_R0, &r0) < 0)
1194 #elif defined (SPARC) || defined (SPARC64)
1195 /* Everything we need is in the current register set. */
1196 if (ptrace(PTRACE_GETREGS,pid,(char *)®s,0) < 0)
1199 /* If we are entering, then disassemble the syscall trap. */
1200 if (!(tcp->flags & TCB_INSYSCALL)) {
1201 /* Retrieve the syscall trap instruction. */
1203 trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
1204 #if defined(SPARC64)
1210 /* Disassemble the trap to see what personality to use. */
1213 /* Linux/SPARC syscall trap. */
1217 /* Linux/SPARC64 syscall trap. */
1221 /* SunOS syscall trap. (pers 1) */
1222 fprintf(stderr,"syscall: SunOS no support\n");
1225 /* Solaris 2.x syscall trap. (per 2) */
1229 /* NetBSD/FreeBSD syscall trap. */
1230 fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1233 /* Solaris 2.x gettimeofday */
1237 /* Unknown syscall trap. */
1238 if(tcp->flags & TCB_WAITEXECVE) {
1239 tcp->flags &= ~TCB_WAITEXECVE;
1242 #if defined (SPARC64)
1243 fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc);
1245 fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
1250 /* Extract the system call number from the registers. */
1251 if (trap == 0x91d02027)
1257 memmove (®s.r_o0, ®s.r_o1, 7*sizeof(regs.r_o0));
1261 if (upeek(pid, PT_GR20, &scno) < 0)
1263 if (!(tcp->flags & TCB_INSYSCALL)) {
1264 /* Check if we return from execve. */
1265 if ((tcp->flags & TCB_WAITEXECVE)) {
1266 tcp->flags &= ~TCB_WAITEXECVE;
1272 * In the new syscall ABI, the system call number is in R3.
1274 if (upeek(pid, 4*(REG_REG0+3), &scno) < 0)
1278 /* Odd as it may seem, a glibc bug has been known to cause
1279 glibc to issue bogus negative syscall numbers. So for
1280 our purposes, make strace print what it *should* have been */
1281 long correct_scno = (scno & 0xff);
1284 "Detected glibc bug: bogus system call number = %ld, "
1285 "correcting to %ld\n",
1288 scno = correct_scno;
1292 if (!(tcp->flags & TCB_INSYSCALL)) {
1293 /* Check if we return from execve. */
1294 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1295 tcp->flags &= ~TCB_WAITEXECVE;
1300 if (upeek(pid, REG_SYSCALL, &scno) < 0)
1304 if (!(tcp->flags & TCB_INSYSCALL)) {
1305 /* Check if we return from execve. */
1306 if (tcp->flags & TCB_WAITEXECVE) {
1307 tcp->flags &= ~TCB_WAITEXECVE;
1314 if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
1317 /* new syscall ABI returns result in R0 */
1318 if (upeek(pid, 4*REG_REG0, (long *)&r0) < 0)
1321 /* ABI defines result returned in r9 */
1322 if (upeek(pid, REG_GENERAL(9), (long *)&r9) < 0)
1327 #ifdef HAVE_PR_SYSCALL
1328 scno = tcp->status.PR_SYSCALL;
1329 #else /* !HAVE_PR_SYSCALL */
1331 scno = tcp->status.PR_WHAT;
1333 if (pread(tcp->pfd_reg, ®s, sizeof(regs), 0) < 0) {
1337 switch (regs.r_eax) {
1340 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1346 #endif /* FREEBSD */
1347 #endif /* !HAVE_PR_SYSCALL */
1348 #endif /* USE_PROCFS */
1349 if (!(tcp->flags & TCB_INSYSCALL))
1359 long scno = tcp->scno;
1360 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1361 scno = sysent[scno].native_scno;
1363 scno += NR_SYSCALL_BASE;
1373 #else /* USE_PROCFS */
1374 int scno = known_scno(tcp);
1376 if (!(tcp->flags & TCB_INSYSCALL)) {
1377 if (tcp->status.PR_WHY != PR_SYSENTRY) {
1381 || scno == SYS_vfork
1382 #endif /* SYS_vfork */
1384 || scno == SYS_fork1
1385 #endif /* SYS_fork1 */
1387 || scno == SYS_forkall
1388 #endif /* SYS_forkall */
1390 || scno == SYS_rfork1
1391 #endif /* SYS_fork1 */
1393 || scno == SYS_rforkall
1394 #endif /* SYS_rforkall */
1396 /* We are returning in the child, fake it. */
1397 tcp->status.PR_WHY = PR_SYSENTRY;
1399 tcp->status.PR_WHY = PR_SYSEXIT;
1402 fprintf(stderr, "syscall: missing entry\n");
1403 tcp->flags |= TCB_INSYSCALL;
1408 if (tcp->status.PR_WHY != PR_SYSEXIT) {
1409 fprintf(stderr, "syscall: missing exit\n");
1410 tcp->flags &= ~TCB_INSYSCALL;
1413 #endif /* USE_PROCFS */
1415 if (!(tcp->flags & TCB_INSYSCALL)) {
1417 fprintf(stderr, "syscall: missing entry\n");
1418 tcp->flags |= TCB_INSYSCALL;
1425 * This happens when a signal handler
1426 * for a signal which interrupted a
1427 * a system call makes another system call.
1429 fprintf(stderr, "syscall: missing exit\n");
1431 tcp->flags &= ~TCB_INSYSCALL;
1437 if (upeek(pid, 4*EAX, &eax) < 0)
1439 if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1441 fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1444 #elif defined (X86_64)
1445 if (upeek(pid, 8*RAX, &rax) < 0)
1447 if (current_personality == 1)
1448 rax = (long int)(int)rax; /* sign extend from 32 bits */
1449 if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1451 fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1454 #elif defined (S390) || defined (S390X)
1455 if (upeek(pid, PT_GPR2, &gpr2) < 0)
1457 if (syscall_mode != -ENOSYS)
1458 syscall_mode = tcp->scno;
1459 if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
1461 fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1464 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1465 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1466 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1468 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1469 * flag set for the post-execve SIGTRAP to see and reset.
1473 #elif defined (POWERPC)
1474 # define SO_MASK 0x10000000
1475 if (upeek(pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1477 if (upeek(pid, sizeof(unsigned long)*PT_R3, &result) < 0)
1479 if (flags & SO_MASK)
1481 #elif defined (M68K)
1482 if (upeek(pid, 4*PT_D0, &d0) < 0)
1484 if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1486 fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1493 #elif defined (HPPA)
1494 if (upeek(pid, PT_GR28, &r28) < 0)
1497 if (upeek(pid, PT_R10, &r10) < 0)
1499 if (upeek(pid, PT_R8, &r8) < 0)
1501 if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1503 fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1517 #if defined(S390) || defined(S390X)
1518 if (gpr2 && (unsigned) -gpr2 < nerrnos) {
1526 #else /* !S390 && !S390X */
1528 if (eax < 0 && -eax < nerrnos) {
1538 if (rax < 0 && -rax < nerrnos) {
1552 if (err < 0 && -err < nerrnos) {
1580 if (result && (unsigned long) -result < nerrnos) {
1585 tcp->u_rval = result;
1588 #else /* !POWERPC */
1590 if (d0 && (unsigned) -d0 < nerrnos) {
1600 if (regs.ARM_r0 && (unsigned) -regs.ARM_r0 < nerrnos) {
1602 u_error = -regs.ARM_r0;
1605 tcp->u_rval = regs.ARM_r0;
1620 if (regs.r_psr & PSR_C) {
1622 u_error = regs.r_o0;
1625 tcp->u_rval = regs.r_o0;
1630 if (regs.r_tstate & 0x1100000000UL) {
1632 u_error = regs.r_o0;
1635 tcp->u_rval = regs.r_o0;
1638 #else /* !SPARC64 */
1640 if (r28 && (unsigned) -r28 < nerrnos) {
1650 /* interpret R0 as return value or error number */
1651 if (r0 && (unsigned) -r0 < nerrnos) {
1661 /* interpret result as return value or error number */
1662 if (r9 && (unsigned) -r9 < nerrnos) {
1674 #endif /* SPARC64 */
1678 #endif /* POWERPC */
1683 #endif /* S390 || S390X */
1686 /* get error code from user struct */
1687 if (upeek(pid, uoff(u_error), &u_error) < 0)
1689 u_error >>= 24; /* u_error is a char */
1691 /* get system call return value */
1692 if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
1697 /* Judicious guessing goes a long way. */
1698 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1700 u_error = tcp->status.pr_reg[R_O0];
1703 tcp->u_rval = tcp->status.pr_reg[R_O0];
1708 /* Wanna know how to kill an hour single-stepping? */
1709 if (tcp->status.PR_REG[EFL] & 0x1) {
1711 u_error = tcp->status.PR_REG[EAX];
1714 tcp->u_rval = tcp->status.PR_REG[EAX];
1715 #ifdef HAVE_LONG_LONG
1717 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1718 tcp->status.PR_REG[EAX];
1724 /* Wanna know how to kill an hour single-stepping? */
1725 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1727 u_error = tcp->status.PR_REG[RAX];
1730 tcp->u_rval = tcp->status.PR_REG[RAX];
1735 if (tcp->status.pr_reg[CTX_A3]) {
1737 u_error = tcp->status.pr_reg[CTX_V0];
1740 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1746 if (regs.r_eflags & PSL_C) {
1748 u_error = regs.r_eax;
1750 tcp->u_rval = regs.r_eax;
1752 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1755 #endif /* FREEBSD */
1756 tcp->u_error = u_error;
1761 force_result(tcp, error, rval)
1767 #if defined(S390) || defined(S390X)
1768 gpr2 = error ? -error : rval;
1769 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1771 #else /* !S390 && !S390X */
1773 eax = error ? -error : rval;
1774 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1778 rax = error ? -error : rval;
1779 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
1784 r8 = error ? -error : rval;
1785 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1797 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1798 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1811 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1812 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1816 if (upeek(tcp->pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1826 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1827 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
1829 #else /* !POWERPC */
1831 d0 = error ? -error : rval;
1832 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1836 regs.ARM_r0 = error ? -error : rval;
1837 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
1849 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1850 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1854 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0)
1857 regs.r_psr |= PSR_C;
1861 regs.r_psr &= ~PSR_C;
1864 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0)
1868 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0)
1871 regs.r_tstate |= 0x1100000000UL;
1875 regs.r_tstate &= ~0x1100000000UL;
1878 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0)
1880 #else /* !SPARC64 */
1882 r28 = error ? -error : rval;
1883 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1887 r0 = error ? -error : rval;
1888 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1892 r9 = error ? -error : rval;
1893 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1899 #endif /* SPARC64 */
1903 #endif /* POWERPC */
1908 #endif /* S390 || S390X */
1911 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1913 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1921 if (pread(tcp->pfd_reg, ®s, sizeof(regs), 0) < 0) {
1926 regs.r_eflags |= PSL_C;
1930 regs.r_eflags &= ~PSL_C;
1933 if (pwrite(tcp->pfd_reg, ®s, sizeof(regs), 0) < 0) {
1937 #endif /* FREEBSD */
1939 /* All branches reach here on success (only). */
1940 tcp->u_error = error;
1951 #endif /* !USE_PROCFS */
1953 #if defined(S390) || defined(S390X)
1956 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1957 tcp->u_nargs = sysent[tcp->scno].nargs;
1959 tcp->u_nargs = MAX_ARGS;
1960 for (i = 0; i < tcp->u_nargs; i++) {
1961 if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
1965 #elif defined (ALPHA)
1968 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1969 tcp->u_nargs = sysent[tcp->scno].nargs;
1971 tcp->u_nargs = MAX_ARGS;
1972 for (i = 0; i < tcp->u_nargs; i++) {
1973 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1974 * for scno somewhere above here!
1976 if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1980 #elif defined (IA64)
1983 unsigned long *out0, *rbs_end, cfm, sof, sol, i;
1984 /* be backwards compatible with kernel < 2.4.4... */
1986 # define PT_RBS_END PT_AR_BSP
1989 if (upeek(pid, PT_RBS_END, (long *) &rbs_end) < 0)
1991 if (upeek(pid, PT_CFM, (long *) &cfm) < 0)
1994 sof = (cfm >> 0) & 0x7f;
1995 sol = (cfm >> 7) & 0x7f;
1996 out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
1998 if (tcp->scno >= 0 && tcp->scno < nsyscalls
1999 && sysent[tcp->scno].nargs != -1)
2000 tcp->u_nargs = sysent[tcp->scno].nargs;
2002 tcp->u_nargs = MAX_ARGS;
2003 for (i = 0; i < tcp->u_nargs; ++i) {
2004 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2005 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2011 if (/* EBX = out0 */
2012 upeek(pid, PT_R11, (long *) &tcp->u_arg[0]) < 0
2014 || upeek(pid, PT_R9, (long *) &tcp->u_arg[1]) < 0
2016 || upeek(pid, PT_R10, (long *) &tcp->u_arg[2]) < 0
2018 || upeek(pid, PT_R14, (long *) &tcp->u_arg[3]) < 0
2020 || upeek(pid, PT_R15, (long *) &tcp->u_arg[4]) < 0
2022 || upeek(pid, PT_R13, (long *) &tcp->u_arg[5]) < 0)
2025 for (i = 0; i < 6; ++i)
2026 /* truncate away IVE sign-extension */
2027 tcp->u_arg[i] &= 0xffffffff;
2029 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2030 && sysent[tcp->scno].nargs != -1)
2031 tcp->u_nargs = sysent[tcp->scno].nargs;
2036 #elif defined (MIPS)
2041 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2042 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2044 nargs = tcp->u_nargs = MAX_ARGS;
2046 if(upeek(pid, REG_SP, &sp) < 0)
2048 for(i = 0; i < 4; i++) {
2049 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
2052 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2053 (char *)(tcp->u_arg + 4));
2055 for(i = 0; i < nargs; i++) {
2056 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
2061 #elif defined (POWERPC)
2063 #define PT_ORIG_R3 34
2067 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2068 tcp->u_nargs = sysent[tcp->scno].nargs;
2070 tcp->u_nargs = MAX_ARGS;
2071 for (i = 0; i < tcp->u_nargs; i++) {
2072 if (upeek(pid, (i==0) ?
2073 (sizeof(unsigned long)*PT_ORIG_R3) :
2074 ((i+PT_R3)*sizeof(unsigned long)),
2075 &tcp->u_arg[i]) < 0)
2079 #elif defined (SPARC) || defined (SPARC64)
2083 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2084 tcp->u_nargs = sysent[tcp->scno].nargs;
2086 tcp->u_nargs = MAX_ARGS;
2087 for (i = 0; i < tcp->u_nargs; i++)
2088 tcp->u_arg[i] = *((®s.r_o0) + i);
2090 #elif defined (HPPA)
2094 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2095 tcp->u_nargs = sysent[tcp->scno].nargs;
2097 tcp->u_nargs = MAX_ARGS;
2098 for (i = 0; i < tcp->u_nargs; i++) {
2099 if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
2107 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2108 tcp->u_nargs = sysent[tcp->scno].nargs;
2110 tcp->u_nargs = MAX_ARGS;
2111 for (i = 0; i < tcp->u_nargs; i++)
2112 tcp->u_arg[i] = regs.uregs[i];
2117 static int syscall_regs[] = {
2118 REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2119 REG_REG0, REG_REG0+1, REG_REG0+2
2122 tcp->u_nargs = sysent[tcp->scno].nargs;
2123 for (i = 0; i < tcp->u_nargs; i++) {
2124 if (upeek(pid, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2131 /* Registers used by SH5 Linux system calls for parameters */
2132 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2135 * TODO: should also check that the number of arguments encoded
2136 * in the trap number matches the number strace expects.
2139 assert(sysent[tcp->scno].nargs <
2140 sizeof(syscall_regs)/sizeof(syscall_regs[0]));
2143 tcp->u_nargs = sysent[tcp->scno].nargs;
2144 for (i = 0; i < tcp->u_nargs; i++) {
2145 if (upeek(pid, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2150 #elif defined(X86_64)
2153 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2154 {RDI,RSI,RDX,R10,R8,R9}, /* x86-64 ABI */
2155 {RBX,RCX,RDX,RSI,RDI,RBP} /* i386 ABI */
2158 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2159 tcp->u_nargs = sysent[tcp->scno].nargs;
2161 tcp->u_nargs = MAX_ARGS;
2162 for (i = 0; i < tcp->u_nargs; i++) {
2163 if (upeek(pid, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
2167 #else /* Other architecture (like i386) (32bits specific) */
2170 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2171 tcp->u_nargs = sysent[tcp->scno].nargs;
2173 tcp->u_nargs = MAX_ARGS;
2174 for (i = 0; i < tcp->u_nargs; i++) {
2175 if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
2184 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2185 tcp->u_nargs = sysent[tcp->scno].nargs;
2187 tcp->u_nargs = MAX_ARGS;
2188 for (i = 0; i < tcp->u_nargs; i++) {
2191 if (upeek(pid, uoff(u_arg[0]) +
2192 (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2200 * SGI is broken: even though it has pr_sysarg, it doesn't
2201 * set them on system call entry. Get a clue.
2203 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2204 tcp->u_nargs = sysent[tcp->scno].nargs;
2206 tcp->u_nargs = tcp->status.pr_nsysarg;
2207 if (tcp->u_nargs > 4) {
2208 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2209 4*sizeof(tcp->u_arg[0]));
2210 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2211 (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2214 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2215 tcp->u_nargs*sizeof(tcp->u_arg[0]));
2219 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2221 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2222 tcp->u_nargs = sysent[tcp->scno].nargs;
2224 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2225 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2226 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2227 #elif defined (HAVE_PR_SYSCALL)
2228 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2229 tcp->u_nargs = sysent[tcp->scno].nargs;
2231 tcp->u_nargs = tcp->status.pr_nsysarg;
2234 for (i = 0; i < tcp->u_nargs; i++)
2235 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2237 #elif defined (I386)
2238 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2239 tcp->u_nargs = sysent[tcp->scno].nargs;
2242 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2243 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2245 I DONT KNOW WHAT TO DO
2246 #endif /* !HAVE_PR_SYSCALL */
2249 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2250 sysent[tcp->scno].nargs > tcp->status.val)
2251 tcp->u_nargs = sysent[tcp->scno].nargs;
2253 tcp->u_nargs = tcp->status.val;
2254 if (tcp->u_nargs < 0)
2256 if (tcp->u_nargs > MAX_ARGS)
2257 tcp->u_nargs = MAX_ARGS;
2258 switch(regs.r_eax) {
2260 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2261 regs.r_esp + sizeof(int) + sizeof(quad_t));
2264 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2265 regs.r_esp + 2 * sizeof(int));
2268 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2269 regs.r_esp + sizeof(int));
2272 #endif /* FREEBSD */
2284 /* Measure the exit time as early as possible to avoid errors. */
2285 if (dtime && (tcp->flags & TCB_INSYSCALL))
2286 gettimeofday(&tv, NULL);
2288 res = get_scno(tcp);
2292 res = syscall_fixup(tcp);
2296 if (tcp->flags & TCB_INSYSCALL) {
2298 res = get_error(tcp);
2302 internal_syscall(tcp);
2303 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2304 !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2305 tcp->flags &= ~TCB_INSYSCALL;
2309 if (tcp->flags & TCB_REPRINT) {
2312 if (tcp->scno >= nsyscalls || tcp->scno < 0)
2313 tprintf("syscall_%lu", tcp->scno);
2315 tprintf("%s", sysent[tcp->scno].sys_name);
2316 tprintf(" resumed> ");
2319 if (cflag && tcp->scno < nsyscalls && tcp->scno >= 0) {
2320 if (counts == NULL) {
2321 counts = calloc(sizeof *counts, nsyscalls);
2322 if (counts == NULL) {
2324 strace: out of memory for call counts\n");
2329 counts[tcp->scno].calls++;
2331 counts[tcp->scno].errors++;
2332 tv_sub(&tv, &tv, &tcp->etime);
2334 if (tv_cmp(&tv, &tcp->dtime) > 0) {
2335 static struct timeval one_tick;
2336 if (one_tick.tv_usec == 0) {
2337 /* Initialize it. */
2338 struct itimerval it;
2339 memset(&it, 0, sizeof it);
2340 it.it_interval.tv_usec = 1;
2341 setitimer(ITIMER_REAL, &it, NULL);
2342 getitimer(ITIMER_REAL, &it);
2343 one_tick = it.it_interval;
2346 if (tv_nz(&tcp->dtime))
2348 else if (tv_cmp(&tv, &one_tick) > 0) {
2349 if (tv_cmp(&shortest, &one_tick) < 0)
2356 if (tv_cmp(&tv, &shortest) < 0)
2358 tv_add(&counts[tcp->scno].time,
2359 &counts[tcp->scno].time, &tv);
2360 tcp->flags &= ~TCB_INSYSCALL;
2364 if (tcp->scno >= nsyscalls || tcp->scno < 0
2365 || (qual_flags[tcp->scno] & QUAL_RAW))
2366 sys_res = printargs(tcp);
2368 if (not_failing_only && tcp->u_error)
2369 return 0; /* ignore failed syscalls */
2370 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2372 u_error = tcp->u_error;
2375 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2376 qual_flags[tcp->scno] & QUAL_RAW) {
2378 tprintf("= -1 (errno %ld)", u_error);
2380 tprintf("= %#lx", tcp->u_rval);
2382 else if (!(sys_res & RVAL_NONE) && u_error) {
2386 tprintf("= ? ERESTARTSYS (To be restarted)");
2388 case ERESTARTNOINTR:
2389 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2391 case ERESTARTNOHAND:
2392 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2394 case ERESTART_RESTARTBLOCK:
2395 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2401 tprintf("E??? (errno %ld)", u_error);
2402 else if (u_error < nerrnos)
2403 tprintf("%s (%s)", errnoent[u_error],
2406 tprintf("ERRNO_%ld (%s)", u_error,
2412 if (sys_res & RVAL_NONE)
2415 switch (sys_res & RVAL_MASK) {
2417 tprintf("= %#lx", tcp->u_rval);
2420 tprintf("= %#lo", tcp->u_rval);
2423 tprintf("= %lu", tcp->u_rval);
2426 tprintf("= %ld", tcp->u_rval);
2428 #ifdef HAVE_LONG_LONG
2430 tprintf("= %#llx", tcp->u_lrval);
2433 tprintf("= %#llo", tcp->u_lrval);
2435 case RVAL_LUDECIMAL:
2436 tprintf("= %llu", tcp->u_lrval);
2439 tprintf("= %lld", tcp->u_lrval);
2444 "invalid rval format\n");
2448 if ((sys_res & RVAL_STR) && tcp->auxstr)
2449 tprintf(" (%s)", tcp->auxstr);
2452 tv_sub(&tv, &tv, &tcp->etime);
2453 tprintf(" <%ld.%06ld>",
2454 (long) tv.tv_sec, (long) tv.tv_usec);
2459 if (fflush(tcp->outf) == EOF)
2461 tcp->flags &= ~TCB_INSYSCALL;
2465 /* Entering system call */
2466 res = syscall_enter(tcp);
2470 switch (known_scno(tcp)) {
2472 #if !defined (ALPHA) && !defined(SPARC) && !defined(SPARC64) && !defined(MIPS) && !defined(HPPA)
2473 case SYS_socketcall:
2474 decode_subcall(tcp, SYS_socket_subcall,
2475 SYS_socket_nsubcalls, deref_style);
2478 decode_subcall(tcp, SYS_ipc_subcall,
2479 SYS_ipc_nsubcalls, shift_style);
2481 #endif /* !ALPHA && !MIPS && !SPARC && !SPARC64 && !HPPA */
2482 #if defined (SPARC) || defined (SPARC64)
2483 case SYS_socketcall:
2484 sparc_socket_decode (tcp);
2489 #ifdef SYS_pgrpsys_subcall
2491 decode_subcall(tcp, SYS_pgrpsys_subcall,
2492 SYS_pgrpsys_nsubcalls, shift_style);
2494 #endif /* SYS_pgrpsys_subcall */
2495 #ifdef SYS_sigcall_subcall
2497 decode_subcall(tcp, SYS_sigcall_subcall,
2498 SYS_sigcall_nsubcalls, mask_style);
2500 #endif /* SYS_sigcall_subcall */
2502 decode_subcall(tcp, SYS_msgsys_subcall,
2503 SYS_msgsys_nsubcalls, shift_style);
2506 decode_subcall(tcp, SYS_shmsys_subcall,
2507 SYS_shmsys_nsubcalls, shift_style);
2510 decode_subcall(tcp, SYS_semsys_subcall,
2511 SYS_semsys_nsubcalls, shift_style);
2515 decode_subcall(tcp, SYS_utssys_subcall,
2516 SYS_utssys_nsubcalls, shift_style);
2520 decode_subcall(tcp, SYS_sysfs_subcall,
2521 SYS_sysfs_nsubcalls, shift_style);
2524 decode_subcall(tcp, SYS_spcall_subcall,
2525 SYS_spcall_nsubcalls, shift_style);
2527 #ifdef SYS_context_subcall
2529 decode_subcall(tcp, SYS_context_subcall,
2530 SYS_context_nsubcalls, shift_style);
2532 #endif /* SYS_context_subcall */
2533 #ifdef SYS_door_subcall
2535 decode_subcall(tcp, SYS_door_subcall,
2536 SYS_door_nsubcalls, door_style);
2538 #endif /* SYS_door_subcall */
2539 #ifdef SYS_kaio_subcall
2541 decode_subcall(tcp, SYS_kaio_subcall,
2542 SYS_kaio_nsubcalls, shift_style);
2550 decode_subcall(tcp, 0, 0, table_style);
2555 decode_subcall(tcp, SYS_semsys_subcall,
2556 SYS_semsys_nsubcalls, shift_style);
2559 decode_subcall(tcp, SYS_msgsys_subcall,
2560 SYS_msgsys_nsubcalls, shift_style);
2563 decode_subcall(tcp, SYS_shmsys_subcall,
2564 SYS_shmsys_nsubcalls, shift_style);
2569 internal_syscall(tcp);
2570 if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2571 tcp->flags |= TCB_INSYSCALL;
2576 gettimeofday(&tcp->etime, NULL);
2577 tcp->flags |= TCB_INSYSCALL;
2582 tcp->flags &= ~TCB_REPRINT;
2584 if (tcp->scno >= nsyscalls || tcp->scno < 0)
2585 tprintf("syscall_%lu(", tcp->scno);
2587 tprintf("%s(", sysent[tcp->scno].sys_name);
2588 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2589 ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2590 sys_res = printargs(tcp);
2592 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2593 if (fflush(tcp->outf) == EOF)
2595 tcp->flags |= TCB_INSYSCALL;
2596 /* Measure the entrance time as late as possible to avoid errors. */
2598 gettimeofday(&tcp->etime, NULL);
2606 if (entering(tcp)) {
2609 for (i = 0; i < tcp->u_nargs; i++)
2610 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2622 #if defined (SPARC) || defined (SPARC64)
2624 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0)
2628 if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
2631 if (upeek(tcp->pid, PT_R9, &val) < 0)
2633 #endif /* SPARC || SPARC64 */
2637 if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
2643 val = tcp->status.PR_REG[R_O1];
2646 val = tcp->status.PR_REG[EDX];
2649 val = tcp->status.PR_REG[RDX];
2652 val = tcp->status.PR_REG[CTX_V1];
2657 pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
2664 * Apparently, indirect system calls have already be converted by ptrace(2),
2665 * so if you see "indir" this program has gone astray.
2673 if (entering(tcp)) {
2674 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2675 fprintf(stderr, "Bogus syscall: %u\n", scno);
2678 nargs = sysent[scno].nargs;
2679 tprintf("%s", sysent[scno].sys_name);
2680 for (i = 0; i < nargs; i++)
2681 tprintf(", %#lx", tcp->u_arg[i+1]);
2691 return -tv_cmp(&counts[*((int *) a)].time, &counts[*((int *) b)].time);
2699 return strcmp(sysent[*((int *) a)].sys_name,
2700 sysent[*((int *) b)].sys_name);
2708 int m = counts[*((int *) a)].calls, n = counts[*((int *) b)].calls;
2710 return (m < n) ? 1 : (m > n) ? -1 : 0;
2713 static int (*sortfun)();
2714 static struct timeval overhead = { -1, -1 };
2720 if (strcmp(sortby, "time") == 0)
2722 else if (strcmp(sortby, "calls") == 0)
2723 sortfun = count_cmp;
2724 else if (strcmp(sortby, "name") == 0)
2725 sortfun = syscall_cmp;
2726 else if (strcmp(sortby, "nothing") == 0)
2729 fprintf(stderr, "invalid sortby: `%s'\n", sortby);
2734 void set_overhead(n)
2737 overhead.tv_sec = n / 1000000;
2738 overhead.tv_usec = n % 1000000;
2746 int call_cum, error_cum;
2747 struct timeval tv_cum, dtv;
2749 char *dashes = "-------------------------";
2752 int *sorted_count = malloc(nsyscalls * sizeof(int));
2754 call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
2755 if (overhead.tv_sec == -1) {
2756 tv_mul(&overhead, &shortest, 8);
2757 tv_div(&overhead, &overhead, 10);
2759 for (i = 0; i < nsyscalls; i++) {
2760 sorted_count[i] = i;
2761 if (counts == NULL || counts[i].calls == 0)
2763 tv_mul(&dtv, &overhead, counts[i].calls);
2764 tv_sub(&counts[i].time, &counts[i].time, &dtv);
2765 call_cum += counts[i].calls;
2766 error_cum += counts[i].errors;
2767 tv_add(&tv_cum, &tv_cum, &counts[i].time);
2769 if (counts && sortfun)
2770 qsort((void *) sorted_count, nsyscalls, sizeof(int), sortfun);
2771 fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",
2772 "% time", "seconds", "usecs/call",
2773 "calls", "errors", "syscall");
2774 fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2775 dashes, dashes, dashes, dashes, dashes, dashes);
2777 for (i = 0; i < nsyscalls; i++) {
2778 j = sorted_count[i];
2779 if (counts[j].calls == 0)
2781 tv_div(&dtv, &counts[j].time, counts[j].calls);
2782 if (counts[j].errors)
2783 sprintf(error_str, "%d", counts[j].errors);
2785 error_str[0] = '\0';
2786 percent = (100.0 * tv_float(&counts[j].time)
2787 / tv_float(&tv_cum));
2788 fprintf(outf, "%6.2f %4ld.%06ld %11ld %9d %9.9s %s\n",
2789 percent, (long) counts[j].time.tv_sec,
2790 (long) counts[j].time.tv_usec,
2791 (long) 1000000 * dtv.tv_sec + dtv.tv_usec,
2793 error_str, sysent[j].sys_name);
2798 fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2799 dashes, dashes, dashes, dashes, dashes, dashes);
2801 sprintf(error_str, "%d", error_cum);
2803 error_str[0] = '\0';
2804 fprintf(outf, "%6.6s %4ld.%06ld %11.11s %9d %9.9s %s\n",
2805 "100.00", (long) tv_cum.tv_sec, (long) tv_cum.tv_usec, "",
2806 call_cum, error_str, "total");