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