]> granicus.if.org Git - strace/commitdiff
2007-03-29 Vladimir Nadvornik <nadvornik@suse.cz>
authorDmitry V. Levin <ldv@altlinux.org>
Sat, 30 Jun 2007 11:37:09 +0000 (11:37 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Sat, 30 Jun 2007 11:37:09 +0000 (11:37 +0000)
    Dmitry V. Levin <ldv@altlinux.org>

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
Makefile.am
defs.h
ioctl.c
scsi.c [new file with mode: 0644]

index fac78fae920986e9eaecc4ac31ecb217ba079625..f603a8ae5be2982f5d4c9e73b776b4edd5818962 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-03-29  Vladimir Nadvornik <nadvornik@suse.cz>
+           Dmitry V. Levin <ldv@altlinux.org>
+
+       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 <ldv@altlinux.org>
 
        * util.c (tv_mul): Multiply tv_usec properly.
index a9972fe2a22c81aee02cdabb0ae05e7d61699d7e..04a9acf8820569229a1f41007c8f9034e993600e 100644 (file)
@@ -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 c25fde80546fd748ba20fb40a7bc2d2967fa52ee..7f9af82c5fa02ac052672f3e72c639bdc9f051b7 100644 (file)
--- 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 d99b669adc78d1450a14001073ed36e875620fbd..906c71efac029d48391a8c8c772bd438a1c67f5e 100644 (file)
--- 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 (file)
index 0000000..cc077a9
--- /dev/null
+++ b/scsi.c
@@ -0,0 +1,114 @@
+#include "defs.h"
+
+#ifdef LINUX
+#include <sys/ioctl.h>
+#include <scsi/sg.h>
+
+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 */