qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

strace.c (9391B)


      1 /*
      2  *  System call tracing and debugging
      3  *
      4  *
      5  *  This program is free software; you can redistribute it and/or modify
      6  *  it under the terms of the GNU General Public License as published by
      7  *  the Free Software Foundation; either version 2 of the License, or
      8  *  (at your option) any later version.
      9  *
     10  *  This program is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  *  GNU General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU General Public License
     16  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
     17  */
     18 
     19 #include "qemu/osdep.h"
     20 #include <sys/select.h>
     21 #include <sys/syscall.h>
     22 #include <sys/ioccom.h>
     23 #include <ctype.h>
     24 
     25 #include "qemu.h"
     26 
     27 #include "os-strace.h"  /* OS dependent strace print functions */
     28 
     29 int do_strace;
     30 
     31 /*
     32  * Utility functions
     33  */
     34 static const char *
     35 get_comma(int last)
     36 {
     37     return (last) ? "" : ",";
     38 }
     39 
     40 /*
     41  * Prints out raw parameter using given format.  Caller needs
     42  * to do byte swapping if needed.
     43  */
     44 static void
     45 print_raw_param(const char *fmt, abi_long param, int last)
     46 {
     47     char format[64];
     48 
     49     (void)snprintf(format, sizeof(format), "%s%s", fmt, get_comma(last));
     50     gemu_log(format, param);
     51 }
     52 
     53 static void print_sysctl(const struct syscallname *name, abi_long arg1,
     54         abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
     55         abi_long arg6)
     56 {
     57     uint32_t i;
     58     int32_t *namep;
     59 
     60     gemu_log("%s({ ", name->name);
     61     namep = lock_user(VERIFY_READ, arg1, sizeof(int32_t) * arg2, 1);
     62     if (namep) {
     63         int32_t *p = namep;
     64 
     65         for (i = 0; i < (uint32_t)arg2; i++) {
     66             gemu_log("%d ", tswap32(*p++));
     67         }
     68         unlock_user(namep, arg1, 0);
     69     }
     70     gemu_log("}, %u, 0x" TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ", 0x"
     71         TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ")",
     72         (uint32_t)arg2, arg3, arg4, arg5, arg6);
     73 }
     74 
     75 static void print_execve(const struct syscallname *name, abi_long arg1,
     76         abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
     77         abi_long arg6)
     78 {
     79     abi_ulong arg_ptr_addr;
     80     char *s;
     81 
     82     s = lock_user_string(arg1);
     83     if (s == NULL) {
     84         return;
     85     }
     86     gemu_log("%s(\"%s\",{", name->name, s);
     87     unlock_user(s, arg1, 0);
     88 
     89     for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
     90         abi_ulong *arg_ptr, arg_addr;
     91 
     92         arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
     93         if (!arg_ptr) {
     94             return;
     95         }
     96         arg_addr = tswapl(*arg_ptr);
     97         unlock_user(arg_ptr, arg_ptr_addr, 0);
     98         if (!arg_addr) {
     99             break;
    100         }
    101         if ((s = lock_user_string(arg_addr))) {
    102             gemu_log("\"%s\",", s);
    103             unlock_user(s, arg_addr, 0);
    104         }
    105     }
    106     gemu_log("NULL})");
    107 }
    108 
    109 static void print_ioctl(const struct syscallname *name,
    110         abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4,
    111         abi_long arg5, abi_long arg6)
    112 {
    113     /* Decode the ioctl request */
    114     gemu_log("%s(%d, 0x%0lx { IO%s%s GRP:0x%x('%c') CMD:%d LEN:%d }, 0x"
    115             TARGET_ABI_FMT_lx ", ...)",
    116             name->name,
    117             (int)arg1,
    118             (unsigned long)arg2,
    119             arg2 & IOC_OUT ? "R" : "",
    120             arg2 & IOC_IN ? "W" : "",
    121             (unsigned)IOCGROUP(arg2),
    122             isprint(IOCGROUP(arg2)) ? (char)IOCGROUP(arg2) : '?',
    123             (int)arg2 & 0xFF,
    124             (int)IOCPARM_LEN(arg2),
    125             arg3);
    126 }
    127 
    128 static void print_sysarch(const struct syscallname *name, abi_long arg1,
    129         abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
    130         abi_long arg6)
    131 {
    132     /* This is os dependent. */
    133     do_os_print_sysarch(name, arg1, arg2, arg3, arg4, arg5, arg6);
    134 }
    135 
    136 /*
    137  * Variants for the return value output function
    138  */
    139 
    140 static void print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
    141 {
    142     if (ret == -1) {
    143         gemu_log(" = -1 errno=%d (%s)\n", errno, strerror(errno));
    144     } else {
    145         gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
    146     }
    147 }
    148 
    149 /*
    150  * An array of all of the syscalls we know about
    151  */
    152 
    153 static const struct syscallname freebsd_scnames[] = {
    154 #include "freebsd/strace.list"
    155 };
    156 static const struct syscallname netbsd_scnames[] = {
    157 #include "netbsd/strace.list"
    158 };
    159 static const struct syscallname openbsd_scnames[] = {
    160 #include "openbsd/strace.list"
    161 };
    162 
    163 static void print_syscall(int num, const struct syscallname *scnames,
    164         unsigned int nscnames, abi_long arg1, abi_long arg2, abi_long arg3,
    165         abi_long arg4, abi_long arg5, abi_long arg6)
    166 {
    167     unsigned int i;
    168     const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ","
    169         TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ","
    170         TARGET_ABI_FMT_ld ")";
    171 
    172     gemu_log("%d ", getpid() );
    173 
    174     for (i = 0; i < nscnames; i++) {
    175         if (scnames[i].nr == num) {
    176             if (scnames[i].call != NULL) {
    177                 scnames[i].call(&scnames[i], arg1, arg2, arg3, arg4, arg5,
    178                         arg6);
    179             } else {
    180                 /* XXX: this format system is broken because it uses
    181                    host types and host pointers for strings */
    182                 if (scnames[i].format != NULL) {
    183                     format = scnames[i].format;
    184                 }
    185                 gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4, arg5,
    186                         arg6);
    187             }
    188             return;
    189         }
    190     }
    191     gemu_log("Unknown syscall %d\n", num);
    192 }
    193 
    194 static void print_syscall_ret(int num, abi_long ret,
    195         const struct syscallname *scnames, unsigned int nscnames)
    196 {
    197     unsigned int i;
    198 
    199     for (i = 0; i < nscnames; i++) {
    200         if (scnames[i].nr == num) {
    201             if (scnames[i].result != NULL) {
    202                 scnames[i].result(&scnames[i], ret);
    203             } else {
    204                 if (ret < 0) {
    205                     gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret,
    206                              strerror(-ret));
    207                 } else {
    208                     gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
    209                 }
    210             }
    211             break;
    212         }
    213     }
    214 }
    215 
    216 /*
    217  * The public interface to this module.
    218  */
    219 void print_freebsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
    220         abi_long arg4, abi_long arg5, abi_long arg6)
    221 {
    222 
    223     print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames), arg1, arg2,
    224             arg3, arg4, arg5, arg6);
    225 }
    226 
    227 void print_freebsd_syscall_ret(int num, abi_long ret)
    228 {
    229 
    230     print_syscall_ret(num, ret, freebsd_scnames, ARRAY_SIZE(freebsd_scnames));
    231 }
    232 
    233 void print_netbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
    234         abi_long arg4, abi_long arg5, abi_long arg6)
    235 {
    236 
    237     print_syscall(num, netbsd_scnames, ARRAY_SIZE(netbsd_scnames),
    238                   arg1, arg2, arg3, arg4, arg5, arg6);
    239 }
    240 
    241 void print_netbsd_syscall_ret(int num, abi_long ret)
    242 {
    243 
    244     print_syscall_ret(num, ret, netbsd_scnames, ARRAY_SIZE(netbsd_scnames));
    245 }
    246 
    247 void print_openbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
    248         abi_long arg4, abi_long arg5, abi_long arg6)
    249 {
    250 
    251     print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames), arg1, arg2,
    252             arg3, arg4, arg5, arg6);
    253 }
    254 
    255 void print_openbsd_syscall_ret(int num, abi_long ret)
    256 {
    257 
    258     print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames));
    259 }
    260 
    261 static void
    262 print_signal(abi_ulong arg, int last)
    263 {
    264     const char *signal_name = NULL;
    265     switch (arg) {
    266     case TARGET_SIGHUP:
    267         signal_name = "SIGHUP";
    268         break;
    269     case TARGET_SIGINT:
    270         signal_name = "SIGINT";
    271         break;
    272     case TARGET_SIGQUIT:
    273         signal_name = "SIGQUIT";
    274         break;
    275     case TARGET_SIGILL:
    276         signal_name = "SIGILL";
    277         break;
    278     case TARGET_SIGABRT:
    279         signal_name = "SIGABRT";
    280         break;
    281     case TARGET_SIGFPE:
    282         signal_name = "SIGFPE";
    283         break;
    284     case TARGET_SIGKILL:
    285         signal_name = "SIGKILL";
    286         break;
    287     case TARGET_SIGSEGV:
    288         signal_name = "SIGSEGV";
    289         break;
    290     case TARGET_SIGPIPE:
    291         signal_name = "SIGPIPE";
    292         break;
    293     case TARGET_SIGALRM:
    294         signal_name = "SIGALRM";
    295         break;
    296     case TARGET_SIGTERM:
    297         signal_name = "SIGTERM";
    298         break;
    299     case TARGET_SIGUSR1:
    300         signal_name = "SIGUSR1";
    301         break;
    302     case TARGET_SIGUSR2:
    303         signal_name = "SIGUSR2";
    304         break;
    305     case TARGET_SIGCHLD:
    306         signal_name = "SIGCHLD";
    307         break;
    308     case TARGET_SIGCONT:
    309         signal_name = "SIGCONT";
    310         break;
    311     case TARGET_SIGSTOP:
    312         signal_name = "SIGSTOP";
    313         break;
    314     case TARGET_SIGTTIN:
    315         signal_name = "SIGTTIN";
    316         break;
    317     case TARGET_SIGTTOU:
    318         signal_name = "SIGTTOU";
    319         break;
    320     }
    321     if (signal_name == NULL) {
    322         print_raw_param("%ld", arg, last);
    323         return;
    324     }
    325     gemu_log("%s%s", signal_name, get_comma(last));
    326 }
    327 
    328 void print_taken_signal(int target_signum, const target_siginfo_t *tinfo)
    329 {
    330     /*
    331      * Print the strace output for a signal being taken:
    332      * --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
    333      */
    334     gemu_log("%d ", getpid());
    335     gemu_log("--- ");
    336     print_signal(target_signum, 1);
    337     gemu_log(" ---\n");
    338 }