1*88dae46dSSean Bruno /* 2*88dae46dSSean Bruno * System call tracing and debugging 3*88dae46dSSean Bruno * 4*88dae46dSSean Bruno * 5*88dae46dSSean Bruno * This program is free software; you can redistribute it and/or modify 6*88dae46dSSean Bruno * it under the terms of the GNU General Public License as published by 7*88dae46dSSean Bruno * the Free Software Foundation; either version 2 of the License, or 8*88dae46dSSean Bruno * (at your option) any later version. 9*88dae46dSSean Bruno * 10*88dae46dSSean Bruno * This program is distributed in the hope that it will be useful, 11*88dae46dSSean Bruno * but WITHOUT ANY WARRANTY; without even the implied warranty of 12*88dae46dSSean Bruno * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*88dae46dSSean Bruno * GNU General Public License for more details. 14*88dae46dSSean Bruno * 15*88dae46dSSean Bruno * You should have received a copy of the GNU General Public License 16*88dae46dSSean Bruno * along with this program; if not, see <http://www.gnu.org/licenses/>. 17*88dae46dSSean Bruno */ 18*88dae46dSSean Bruno 1984778508Sblueswir1 #include <stdio.h> 2084778508Sblueswir1 #include <errno.h> 2184778508Sblueswir1 #include <sys/select.h> 2284778508Sblueswir1 #include <sys/types.h> 2384778508Sblueswir1 #include <unistd.h> 2484778508Sblueswir1 #include <sys/syscall.h> 25*88dae46dSSean Bruno #include <sys/ioccom.h> 26*88dae46dSSean Bruno #include <ctype.h> 27*88dae46dSSean Bruno 2884778508Sblueswir1 #include "qemu.h" 2984778508Sblueswir1 30*88dae46dSSean Bruno int do_strace; 3184778508Sblueswir1 3284778508Sblueswir1 /* 3384778508Sblueswir1 * Utility functions 3484778508Sblueswir1 */ 3584778508Sblueswir1 36*88dae46dSSean Bruno static void print_execve(const struct syscallname *name, abi_long arg1, 37*88dae46dSSean Bruno abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, 38*88dae46dSSean Bruno abi_long arg6) 3984778508Sblueswir1 { 4084778508Sblueswir1 abi_ulong arg_ptr_addr; 4184778508Sblueswir1 char *s; 4284778508Sblueswir1 43*88dae46dSSean Bruno s = lock_user_string(arg1); 44*88dae46dSSean Bruno if (s == NULL) { 4584778508Sblueswir1 return; 46*88dae46dSSean Bruno } 4784778508Sblueswir1 gemu_log("%s(\"%s\",{", name->name, s); 4884778508Sblueswir1 unlock_user(s, arg1, 0); 4984778508Sblueswir1 5084778508Sblueswir1 for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { 5118c9a9c3SChristoph Egger abi_ulong *arg_ptr, arg_addr; 5284778508Sblueswir1 5384778508Sblueswir1 arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); 54*88dae46dSSean Bruno if (!arg_ptr) { 5584778508Sblueswir1 return; 56*88dae46dSSean Bruno } 5784778508Sblueswir1 arg_addr = tswapl(*arg_ptr); 5884778508Sblueswir1 unlock_user(arg_ptr, arg_ptr_addr, 0); 59*88dae46dSSean Bruno if (!arg_addr) { 6084778508Sblueswir1 break; 61*88dae46dSSean Bruno } 6284778508Sblueswir1 if ((s = lock_user_string(arg_addr))) { 6384778508Sblueswir1 gemu_log("\"%s\",", s); 6418c9a9c3SChristoph Egger unlock_user(s, arg_addr, 0); 6584778508Sblueswir1 } 6684778508Sblueswir1 } 6784778508Sblueswir1 gemu_log("NULL})"); 6884778508Sblueswir1 } 6984778508Sblueswir1 7084778508Sblueswir1 /* 7184778508Sblueswir1 * Variants for the return value output function 7284778508Sblueswir1 */ 7384778508Sblueswir1 74*88dae46dSSean Bruno static void print_syscall_ret_addr(const struct syscallname *name, abi_long ret) 7584778508Sblueswir1 { 7684778508Sblueswir1 if (ret == -1) { 7784778508Sblueswir1 gemu_log(" = -1 errno=%d (%s)\n", errno, strerror(errno)); 7884778508Sblueswir1 } else { 7984778508Sblueswir1 gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); 8084778508Sblueswir1 } 8184778508Sblueswir1 } 8284778508Sblueswir1 8384778508Sblueswir1 #if 0 /* currently unused */ 8484778508Sblueswir1 static void 8584778508Sblueswir1 print_syscall_ret_raw(struct syscallname *name, abi_long ret) 8684778508Sblueswir1 { 8784778508Sblueswir1 gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); 8884778508Sblueswir1 } 8984778508Sblueswir1 #endif 9084778508Sblueswir1 9184778508Sblueswir1 /* 9284778508Sblueswir1 * An array of all of the syscalls we know about 9384778508Sblueswir1 */ 9484778508Sblueswir1 9584778508Sblueswir1 static const struct syscallname freebsd_scnames[] = { 9684778508Sblueswir1 #include "freebsd/strace.list" 9784778508Sblueswir1 }; 9884778508Sblueswir1 static const struct syscallname netbsd_scnames[] = { 9984778508Sblueswir1 #include "netbsd/strace.list" 10084778508Sblueswir1 }; 10184778508Sblueswir1 static const struct syscallname openbsd_scnames[] = { 10284778508Sblueswir1 #include "openbsd/strace.list" 10384778508Sblueswir1 }; 10484778508Sblueswir1 105*88dae46dSSean Bruno static void print_syscall(int num, const struct syscallname *scnames, 106*88dae46dSSean Bruno unsigned int nscnames, abi_long arg1, abi_long arg2, abi_long arg3, 10784778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6) 10884778508Sblueswir1 { 10984778508Sblueswir1 unsigned int i; 11084778508Sblueswir1 const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," 11184778508Sblueswir1 TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," 11284778508Sblueswir1 TARGET_ABI_FMT_ld ")"; 11384778508Sblueswir1 11484778508Sblueswir1 gemu_log("%d ", getpid() ); 11584778508Sblueswir1 116*88dae46dSSean Bruno for (i = 0; i < nscnames; i++) { 11784778508Sblueswir1 if (scnames[i].nr == num) { 11884778508Sblueswir1 if (scnames[i].call != NULL) { 11984778508Sblueswir1 scnames[i].call(&scnames[i], arg1, arg2, arg3, arg4, arg5, 12084778508Sblueswir1 arg6); 12184778508Sblueswir1 } else { 12284778508Sblueswir1 /* XXX: this format system is broken because it uses 12384778508Sblueswir1 host types and host pointers for strings */ 124*88dae46dSSean Bruno if (scnames[i].format != NULL) { 12584778508Sblueswir1 format = scnames[i].format; 126*88dae46dSSean Bruno } 127*88dae46dSSean Bruno gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4, arg5, 128*88dae46dSSean Bruno arg6); 12984778508Sblueswir1 } 13084778508Sblueswir1 return; 13184778508Sblueswir1 } 132*88dae46dSSean Bruno } 13384778508Sblueswir1 gemu_log("Unknown syscall %d\n", num); 13484778508Sblueswir1 } 13584778508Sblueswir1 136*88dae46dSSean Bruno static void print_syscall_ret(int num, abi_long ret, 137*88dae46dSSean Bruno const struct syscallname *scnames, unsigned int nscnames) 13884778508Sblueswir1 { 13984778508Sblueswir1 unsigned int i; 14084778508Sblueswir1 141*88dae46dSSean Bruno for (i = 0; i < nscnames; i++) { 14284778508Sblueswir1 if (scnames[i].nr == num) { 14384778508Sblueswir1 if (scnames[i].result != NULL) { 14484778508Sblueswir1 scnames[i].result(&scnames[i], ret); 14584778508Sblueswir1 } else { 14684778508Sblueswir1 if (ret < 0) { 14784778508Sblueswir1 gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, 14884778508Sblueswir1 strerror(-ret)); 14984778508Sblueswir1 } else { 15084778508Sblueswir1 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); 15184778508Sblueswir1 } 15284778508Sblueswir1 } 15384778508Sblueswir1 break; 15484778508Sblueswir1 } 15584778508Sblueswir1 } 156*88dae46dSSean Bruno } 15784778508Sblueswir1 15884778508Sblueswir1 /* 15984778508Sblueswir1 * The public interface to this module. 16084778508Sblueswir1 */ 161*88dae46dSSean Bruno void print_freebsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3, 16284778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6) 16384778508Sblueswir1 { 164*88dae46dSSean Bruno 165*88dae46dSSean Bruno print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames), arg1, arg2, 166*88dae46dSSean Bruno arg3, arg4, arg5, arg6); 16784778508Sblueswir1 } 16884778508Sblueswir1 169*88dae46dSSean Bruno void print_freebsd_syscall_ret(int num, abi_long ret) 17084778508Sblueswir1 { 171*88dae46dSSean Bruno 17284778508Sblueswir1 print_syscall_ret(num, ret, freebsd_scnames, ARRAY_SIZE(freebsd_scnames)); 17384778508Sblueswir1 } 17484778508Sblueswir1 175*88dae46dSSean Bruno void print_netbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3, 17684778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6) 17784778508Sblueswir1 { 178*88dae46dSSean Bruno 17984778508Sblueswir1 print_syscall(num, netbsd_scnames, ARRAY_SIZE(netbsd_scnames), 18084778508Sblueswir1 arg1, arg2, arg3, arg4, arg5, arg6); 18184778508Sblueswir1 } 18284778508Sblueswir1 183*88dae46dSSean Bruno void print_netbsd_syscall_ret(int num, abi_long ret) 18484778508Sblueswir1 { 185*88dae46dSSean Bruno 18684778508Sblueswir1 print_syscall_ret(num, ret, netbsd_scnames, ARRAY_SIZE(netbsd_scnames)); 18784778508Sblueswir1 } 18884778508Sblueswir1 189*88dae46dSSean Bruno void print_openbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3, 19084778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6) 19184778508Sblueswir1 { 192*88dae46dSSean Bruno 193*88dae46dSSean Bruno print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames), arg1, arg2, 194*88dae46dSSean Bruno arg3, arg4, arg5, arg6); 19584778508Sblueswir1 } 19684778508Sblueswir1 197*88dae46dSSean Bruno void print_openbsd_syscall_ret(int num, abi_long ret) 19884778508Sblueswir1 { 199*88dae46dSSean Bruno 20084778508Sblueswir1 print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames)); 20184778508Sblueswir1 } 202