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 19 84778508Sblueswir1 #include <stdio.h> 20 84778508Sblueswir1 #include <errno.h> 21 84778508Sblueswir1 #include <sys/select.h> 22 84778508Sblueswir1 #include <sys/types.h> 23 84778508Sblueswir1 #include <unistd.h> 24 84778508Sblueswir1 #include <sys/syscall.h> 25 *88dae46dSSean Bruno #include <sys/ioccom.h> 26 *88dae46dSSean Bruno #include <ctype.h> 27 *88dae46dSSean Bruno 28 84778508Sblueswir1 #include "qemu.h" 29 84778508Sblueswir1 30 *88dae46dSSean Bruno int do_strace; 31 84778508Sblueswir1 32 84778508Sblueswir1 /* 33 84778508Sblueswir1 * Utility functions 34 84778508Sblueswir1 */ 35 84778508Sblueswir1 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) 39 84778508Sblueswir1 { 40 84778508Sblueswir1 abi_ulong arg_ptr_addr; 41 84778508Sblueswir1 char *s; 42 84778508Sblueswir1 43 *88dae46dSSean Bruno s = lock_user_string(arg1); 44 *88dae46dSSean Bruno if (s == NULL) { 45 84778508Sblueswir1 return; 46 *88dae46dSSean Bruno } 47 84778508Sblueswir1 gemu_log("%s(\"%s\",{", name->name, s); 48 84778508Sblueswir1 unlock_user(s, arg1, 0); 49 84778508Sblueswir1 50 84778508Sblueswir1 for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { 51 18c9a9c3SChristoph Egger abi_ulong *arg_ptr, arg_addr; 52 84778508Sblueswir1 53 84778508Sblueswir1 arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); 54 *88dae46dSSean Bruno if (!arg_ptr) { 55 84778508Sblueswir1 return; 56 *88dae46dSSean Bruno } 57 84778508Sblueswir1 arg_addr = tswapl(*arg_ptr); 58 84778508Sblueswir1 unlock_user(arg_ptr, arg_ptr_addr, 0); 59 *88dae46dSSean Bruno if (!arg_addr) { 60 84778508Sblueswir1 break; 61 *88dae46dSSean Bruno } 62 84778508Sblueswir1 if ((s = lock_user_string(arg_addr))) { 63 84778508Sblueswir1 gemu_log("\"%s\",", s); 64 18c9a9c3SChristoph Egger unlock_user(s, arg_addr, 0); 65 84778508Sblueswir1 } 66 84778508Sblueswir1 } 67 84778508Sblueswir1 gemu_log("NULL})"); 68 84778508Sblueswir1 } 69 84778508Sblueswir1 70 84778508Sblueswir1 /* 71 84778508Sblueswir1 * Variants for the return value output function 72 84778508Sblueswir1 */ 73 84778508Sblueswir1 74 *88dae46dSSean Bruno static void print_syscall_ret_addr(const struct syscallname *name, abi_long ret) 75 84778508Sblueswir1 { 76 84778508Sblueswir1 if (ret == -1) { 77 84778508Sblueswir1 gemu_log(" = -1 errno=%d (%s)\n", errno, strerror(errno)); 78 84778508Sblueswir1 } else { 79 84778508Sblueswir1 gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); 80 84778508Sblueswir1 } 81 84778508Sblueswir1 } 82 84778508Sblueswir1 83 84778508Sblueswir1 #if 0 /* currently unused */ 84 84778508Sblueswir1 static void 85 84778508Sblueswir1 print_syscall_ret_raw(struct syscallname *name, abi_long ret) 86 84778508Sblueswir1 { 87 84778508Sblueswir1 gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); 88 84778508Sblueswir1 } 89 84778508Sblueswir1 #endif 90 84778508Sblueswir1 91 84778508Sblueswir1 /* 92 84778508Sblueswir1 * An array of all of the syscalls we know about 93 84778508Sblueswir1 */ 94 84778508Sblueswir1 95 84778508Sblueswir1 static const struct syscallname freebsd_scnames[] = { 96 84778508Sblueswir1 #include "freebsd/strace.list" 97 84778508Sblueswir1 }; 98 84778508Sblueswir1 static const struct syscallname netbsd_scnames[] = { 99 84778508Sblueswir1 #include "netbsd/strace.list" 100 84778508Sblueswir1 }; 101 84778508Sblueswir1 static const struct syscallname openbsd_scnames[] = { 102 84778508Sblueswir1 #include "openbsd/strace.list" 103 84778508Sblueswir1 }; 104 84778508Sblueswir1 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, 107 84778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6) 108 84778508Sblueswir1 { 109 84778508Sblueswir1 unsigned int i; 110 84778508Sblueswir1 const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," 111 84778508Sblueswir1 TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," 112 84778508Sblueswir1 TARGET_ABI_FMT_ld ")"; 113 84778508Sblueswir1 114 84778508Sblueswir1 gemu_log("%d ", getpid() ); 115 84778508Sblueswir1 116 *88dae46dSSean Bruno for (i = 0; i < nscnames; i++) { 117 84778508Sblueswir1 if (scnames[i].nr == num) { 118 84778508Sblueswir1 if (scnames[i].call != NULL) { 119 84778508Sblueswir1 scnames[i].call(&scnames[i], arg1, arg2, arg3, arg4, arg5, 120 84778508Sblueswir1 arg6); 121 84778508Sblueswir1 } else { 122 84778508Sblueswir1 /* XXX: this format system is broken because it uses 123 84778508Sblueswir1 host types and host pointers for strings */ 124 *88dae46dSSean Bruno if (scnames[i].format != NULL) { 125 84778508Sblueswir1 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); 129 84778508Sblueswir1 } 130 84778508Sblueswir1 return; 131 84778508Sblueswir1 } 132 *88dae46dSSean Bruno } 133 84778508Sblueswir1 gemu_log("Unknown syscall %d\n", num); 134 84778508Sblueswir1 } 135 84778508Sblueswir1 136 *88dae46dSSean Bruno static void print_syscall_ret(int num, abi_long ret, 137 *88dae46dSSean Bruno const struct syscallname *scnames, unsigned int nscnames) 138 84778508Sblueswir1 { 139 84778508Sblueswir1 unsigned int i; 140 84778508Sblueswir1 141 *88dae46dSSean Bruno for (i = 0; i < nscnames; i++) { 142 84778508Sblueswir1 if (scnames[i].nr == num) { 143 84778508Sblueswir1 if (scnames[i].result != NULL) { 144 84778508Sblueswir1 scnames[i].result(&scnames[i], ret); 145 84778508Sblueswir1 } else { 146 84778508Sblueswir1 if (ret < 0) { 147 84778508Sblueswir1 gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, 148 84778508Sblueswir1 strerror(-ret)); 149 84778508Sblueswir1 } else { 150 84778508Sblueswir1 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); 151 84778508Sblueswir1 } 152 84778508Sblueswir1 } 153 84778508Sblueswir1 break; 154 84778508Sblueswir1 } 155 84778508Sblueswir1 } 156 *88dae46dSSean Bruno } 157 84778508Sblueswir1 158 84778508Sblueswir1 /* 159 84778508Sblueswir1 * The public interface to this module. 160 84778508Sblueswir1 */ 161 *88dae46dSSean Bruno void print_freebsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3, 162 84778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6) 163 84778508Sblueswir1 { 164 *88dae46dSSean Bruno 165 *88dae46dSSean Bruno print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames), arg1, arg2, 166 *88dae46dSSean Bruno arg3, arg4, arg5, arg6); 167 84778508Sblueswir1 } 168 84778508Sblueswir1 169 *88dae46dSSean Bruno void print_freebsd_syscall_ret(int num, abi_long ret) 170 84778508Sblueswir1 { 171 *88dae46dSSean Bruno 172 84778508Sblueswir1 print_syscall_ret(num, ret, freebsd_scnames, ARRAY_SIZE(freebsd_scnames)); 173 84778508Sblueswir1 } 174 84778508Sblueswir1 175 *88dae46dSSean Bruno void print_netbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3, 176 84778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6) 177 84778508Sblueswir1 { 178 *88dae46dSSean Bruno 179 84778508Sblueswir1 print_syscall(num, netbsd_scnames, ARRAY_SIZE(netbsd_scnames), 180 84778508Sblueswir1 arg1, arg2, arg3, arg4, arg5, arg6); 181 84778508Sblueswir1 } 182 84778508Sblueswir1 183 *88dae46dSSean Bruno void print_netbsd_syscall_ret(int num, abi_long ret) 184 84778508Sblueswir1 { 185 *88dae46dSSean Bruno 186 84778508Sblueswir1 print_syscall_ret(num, ret, netbsd_scnames, ARRAY_SIZE(netbsd_scnames)); 187 84778508Sblueswir1 } 188 84778508Sblueswir1 189 *88dae46dSSean Bruno void print_openbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3, 190 84778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6) 191 84778508Sblueswir1 { 192 *88dae46dSSean Bruno 193 *88dae46dSSean Bruno print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames), arg1, arg2, 194 *88dae46dSSean Bruno arg3, arg4, arg5, arg6); 195 84778508Sblueswir1 } 196 84778508Sblueswir1 197 *88dae46dSSean Bruno void print_openbsd_syscall_ret(int num, abi_long ret) 198 84778508Sblueswir1 { 199 *88dae46dSSean Bruno 200 84778508Sblueswir1 print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames)); 201 84778508Sblueswir1 } 202