From b011af5ef077fcfc2ad967579dcb1e5ed9b3193e Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 30 Jun 2007 11:37:09 +0000 Subject: [PATCH] 2007-03-29 Vladimir Nadvornik Dmitry V. Levin Trace linux SG_IO ioctl arguments and results. * scsi.c: New file. * Makefile.am (strace_SOURCES): Add scsi.c * defs.h (scsi_ioctl): New function. * ioctl.c (ioctl_decode): Use scsi_ioctl(). --- ChangeLog | 9 +++++ Makefile.am | 2 +- defs.h | 1 + ioctl.c | 2 + scsi.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 scsi.c diff --git a/ChangeLog b/ChangeLog index fac78fae..f603a8ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-03-29 Vladimir Nadvornik + Dmitry V. Levin + + Trace linux SG_IO ioctl arguments and results. + * scsi.c: New file. + * Makefile.am (strace_SOURCES): Add scsi.c + * defs.h (scsi_ioctl): New function. + * ioctl.c (ioctl_decode): Use scsi_ioctl(). + 2007-06-28 Dmitry V. Levin * util.c (tv_mul): Multiply tv_usec properly. diff --git a/Makefile.am b/Makefile.am index a9972fe2..04a9acf8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,7 @@ INCLUDES = -I$(OS)/$(ARCH) -I$(srcdir)/$(OS)/$(ARCH) -I$(OS) -I$(srcdir)/$(OS) strace_SOURCES = strace.c syscall.c count.c util.c desc.c file.c ipc.c \ io.c ioctl.c mem.c net.c process.c bjm.c quota.c \ resource.c signal.c sock.c system.c term.c time.c \ - proc.c stream.c + proc.c scsi.c stream.c noinst_HEADERS = defs.h EXTRA_DIST = $(man_MANS) errnoent.sh signalent.sh syscallent.sh ioctlsort.c \ diff --git a/defs.h b/defs.h index c25fde80..7f9af82c 100644 --- a/defs.h +++ b/defs.h @@ -493,6 +493,7 @@ extern int proc_ioctl P((struct tcb *, int, int)); extern int stream_ioctl P((struct tcb *, int, int)); #ifdef LINUX extern int rtc_ioctl P((struct tcb *, long, long)); +extern int scsi_ioctl P((struct tcb *, long, long)); #endif extern void tv_tv P((struct timeval *, int, int)); diff --git a/ioctl.c b/ioctl.c index d99b669a..906c71ef 100644 --- a/ioctl.c +++ b/ioctl.c @@ -152,6 +152,8 @@ long code, arg; #ifdef LINUX case 'p': return rtc_ioctl(tcp, code, arg); + case 0x22: + return scsi_ioctl(tcp, code, arg); #endif default: break; diff --git a/scsi.c b/scsi.c new file mode 100644 index 00000000..cc077a9d --- /dev/null +++ b/scsi.c @@ -0,0 +1,114 @@ +#include "defs.h" + +#ifdef LINUX +#include +#include + +static const struct xlat sg_io_dxfer_direction[] = { + {SG_DXFER_NONE, "SG_DXFER_NONE"}, + {SG_DXFER_TO_DEV, "SG_DXFER_TO_DEV"}, + {SG_DXFER_FROM_DEV, "SG_DXFER_FROM_DEV"}, + {SG_DXFER_TO_FROM_DEV, "SG_DXFER_TO_FROM_DEV"}, + {0, NULL} +}; + +static void +print_sg_io_buffer(struct tcb *tcp, unsigned char *addr, int len) +{ + unsigned char *buf = NULL; + int allocated, i; + + if (len == 0) + return; + allocated = (len > max_strlen) ? max_strlen : len; + if (len < 0 || + (buf = malloc(allocated)) == NULL || + umoven(tcp, (unsigned long) addr, allocated, (char *) buf) < 0) { + tprintf("%p", addr); + free(buf); + return; + } + tprintf("%02x", buf[0]); + for (i = 1; i < allocated; ++i) + tprintf(", %02x", buf[i]); + free(buf); + if (allocated != len) + tprintf(", ..."); +} + +static void +print_sg_io_req(struct tcb *tcp, struct sg_io_hdr *sg_io) +{ + tprintf("{'%c', ", sg_io->interface_id); + printxval(sg_io_dxfer_direction, sg_io->dxfer_direction, + "SG_DXFER_???"); + tprintf(", cmd[%u]=[", sg_io->cmd_len); + print_sg_io_buffer(tcp, sg_io->cmdp, sg_io->cmd_len); + tprintf("], mx_sb_len=%d, ", sg_io->mx_sb_len); + tprintf("iovec_count=%d, ", sg_io->iovec_count); + tprintf("dxfer_len=%u, ", sg_io->dxfer_len); + tprintf("timeout=%u, ", sg_io->timeout); + tprintf("flags=%#x", sg_io->flags); + + if (sg_io->dxfer_direction == SG_DXFER_TO_DEV || + sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) { + tprintf(", data[%u]=[", sg_io->dxfer_len); + printstr(tcp, (unsigned long) sg_io->dxferp, + sg_io->dxfer_len); + tprintf("]"); + } +} + +static void +print_sg_io_res(struct tcb *tcp, struct sg_io_hdr *sg_io) +{ + if (sg_io->dxfer_direction == SG_DXFER_FROM_DEV || + sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) { + tprintf(", data[%u]=[", sg_io->dxfer_len); + printstr(tcp, (unsigned long) sg_io->dxferp, + sg_io->dxfer_len); + tprintf("]"); + } + tprintf(", status=%02x, ", sg_io->status); + tprintf("masked_status=%02x, ", sg_io->masked_status); + tprintf("sb[%u]=[", sg_io->sb_len_wr); + print_sg_io_buffer(tcp, sg_io->sbp, sg_io->sb_len_wr); + tprintf("], host_status=%#x, ", sg_io->host_status); + tprintf("driver_status=%#x, ", sg_io->driver_status); + tprintf("resid=%d, ", sg_io->resid); + tprintf("duration=%d, ", sg_io->duration); + tprintf("info=%#x}", sg_io->info); +} + +int +scsi_ioctl(struct tcb *tcp, long code, long arg) +{ + switch (code) { + case SG_IO: + if (entering(tcp)) { + struct sg_io_hdr sg_io; + + if (umove(tcp, arg, &sg_io) < 0) + tprintf(", %#lx", arg); + else { + tprintf(", "); + print_sg_io_req(tcp, &sg_io); + } + } + if (exiting(tcp)) { + struct sg_io_hdr sg_io; + + if (!syserror(tcp) && umove(tcp, arg, &sg_io) >= 0) + print_sg_io_res(tcp, &sg_io); + else + tprintf("}"); + } + break; + default: + if (entering(tcp)) + tprintf(", %#lx", arg); + break; + } + return 1; +} +#endif /* LINUX */