]> granicus.if.org Git - strace/commitdiff
mtd.c: enhance mtd and ubi ioctl parsers
authorDmitry V. Levin <ldv@altlinux.org>
Tue, 7 Jul 2015 01:12:12 +0000 (04:12 +0300)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 10 Jul 2015 22:52:58 +0000 (22:52 +0000)
Decode as much data on entering syscall as possible.

* xlat/mtd_file_mode_options.in: New file.
* mtd.c: Include <linux/ioctl.h> instead of <sys/ioctl.h>.
Include "xlat/mtd_file_mode_options.h".
Update for RVAL_DECODED.
(mtd_ioctl, ubi_ioctl): Use printnum_int and umove_or_printaddr.

mtd.c
xlat/mtd_file_mode_options.in [new file with mode: 0644]

diff --git a/mtd.c b/mtd.c
index 87a6e5d15fcf1422449af9f5ffa165ae10f585d5..18f8af07a82c022a6038888c9bc038a7421b446c 100644 (file)
--- a/mtd.c
+++ b/mtd.c
@@ -26,7 +26,7 @@
 
 #include "defs.h"
 
-#include <sys/ioctl.h>
+#include <linux/ioctl.h>
 
 /* The mtd api changes quickly, so we have to keep a local copy */
 #include <linux/version.h>
 #endif
 
 #include "xlat/mtd_mode_options.h"
+#include "xlat/mtd_file_mode_options.h"
 #include "xlat/mtd_type_options.h"
 #include "xlat/mtd_flags_options.h"
 #include "xlat/mtd_otp_options.h"
 #include "xlat/mtd_nandecc_options.h"
 
 int
-mtd_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+mtd_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
 {
-       struct mtd_info_user minfo;
-       struct erase_info_user einfo;
-       struct erase_info_user64 einfo64;
-       struct mtd_oob_buf mbuf;
-       struct mtd_oob_buf64 mbuf64;
-       struct region_info_user rinfo;
-       struct otp_info oinfo;
-       struct mtd_ecc_stats estat;
-       struct mtd_write_req mreq;
-       struct nand_oobinfo ninfo;
-       struct nand_ecclayout_user nlay;
-       unsigned int i, j;
-
-       if (entering(tcp))
-               return 0;
+       if (!verbose(tcp))
+               return RVAL_DECODED;
 
        switch (code) {
-
-       case MEMGETINFO:
-               if (!verbose(tcp) || umove(tcp, arg, &minfo) < 0)
-                       return 0;
-
-               tprints(", {type=");
-               printxval(mtd_type_options, minfo.type, "MTD_???");
-               tprints(", flags=");
-               printflags(mtd_flags_options, minfo.flags, "MTD_???");
-               tprintf(", size=%#" PRIx32 ", erasesize=%#" PRIx32,
-                       minfo.size, minfo.erasesize);
-               tprintf(", writesize=%#" PRIx32 ", oobsize=%#" PRIx32,
-                       minfo.writesize, minfo.oobsize);
-               tprintf(", padding=%#" PRIx64 "}",
-                       (uint64_t) minfo.padding);
-               return 1;
-
        case MEMERASE:
        case MEMLOCK:
        case MEMUNLOCK:
-       case MEMISLOCKED:
-               if (!verbose(tcp) || umove(tcp, arg, &einfo) < 0)
-                       return 0;
+       case MEMISLOCKED: {
+               struct erase_info_user einfo;
+
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &einfo))
+                       break;
 
-               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 "}",
+               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 "}",
                        einfo.start, einfo.length);
-               return 1;
+               break;
+       }
 
-       case MEMERASE64:
-               if (!verbose(tcp) || umove(tcp, arg, &einfo64) < 0)
-                       return 0;
+       case MEMERASE64: {
+               struct erase_info_user64 einfo64;
 
-               tprintf(", {start=%#" PRIx64 ", length=%#" PRIx64 "}",
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &einfo64))
+                       break;
+
+               tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 "}",
                        (uint64_t) einfo64.start, (uint64_t) einfo64.length);
-               return 1;
+               break;
+       }
 
        case MEMWRITEOOB:
-       case MEMREADOOB:
-               if (!verbose(tcp) || umove(tcp, arg, &mbuf) < 0)
-                       return 0;
+       case MEMREADOOB: {
+               struct mtd_oob_buf mbuf;
+
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &mbuf))
+                       break;
 
-               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", ptr=...}",
+               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", ptr=...}",
                        mbuf.start, mbuf.length);
-               return 1;
+               break;
+       }
 
        case MEMWRITEOOB64:
-       case MEMREADOOB64:
-               if (!verbose(tcp) || umove(tcp, arg, &mbuf64) < 0)
-                       return 0;
+       case MEMREADOOB64: {
+               struct mtd_oob_buf64 mbuf64;
 
-               tprintf(", {start=%#" PRIx64 ", length=%#" PRIx64 ", ptr=...}",
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &mbuf64))
+                       break;
+
+               tprintf("{start=%#" PRIx64 ", length=%#" PRIx64 ", ptr=...}",
                        (uint64_t) mbuf64.start, (uint64_t) mbuf64.length);
-               return 1;
+               break;
+       }
+
+       case MEMGETREGIONINFO: {
+               struct region_info_user rinfo;
+
+               if (entering(tcp)) {
+                       tprints(", ");
+                       if (umove_or_printaddr(tcp, arg, &rinfo))
+                               break;
+                       tprintf("{regionindex=%#x", rinfo.regionindex);
+                       return 1;
+               } else {
+                       if (syserror(tcp)) {
+                               tprints("}");
+                               break;
+                       }
+                       if (umove(tcp, arg, &rinfo) < 0) {
+                               tprints(", ???}");
+                               break;
+                       }
+                       tprintf(", offset=%#x, erasesize=%#x, numblocks=%#x}",
+                               rinfo.offset, rinfo.erasesize, rinfo.numblocks);
+                       break;
+               }
+       }
+
+       case OTPLOCK: {
+               struct otp_info oinfo;
+
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &oinfo))
+                       break;
+
+               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
+                       oinfo.start, oinfo.length, oinfo.locked);
+               break;
+       }
+
+       case MEMWRITE: {
+               struct mtd_write_req mreq;
 
-       case MEMGETREGIONINFO:
-               if (!verbose(tcp) || umove(tcp, arg, &rinfo) < 0)
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &mreq))
+                       break;
+
+               tprintf("{start=%#" PRIx64 ", len=%#" PRIx64,
+                       (uint64_t) mreq.start, (uint64_t) mreq.len);
+               tprintf(", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64,
+                       (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data);
+               tprintf(", usr_oob=%#" PRIx64 ", mode=",
+                       (uint64_t) mreq.usr_oob);
+               printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
+               tprints(", padding=...}");
+               break;
+       }
+
+       case OTPSELECT: {
+               unsigned int i;
+
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &i))
+                       break;
+
+               tprints("[");
+               printxval(mtd_otp_options, i, "MTD_OTP_???");
+               tprints("]");
+               break;
+       }
+
+       case MTDFILEMODE:
+               tprints(", ");
+               printxval(mtd_file_mode_options, arg, "MTD_FILE_MODE_???");
+               break;
+
+       case MEMGETBADBLOCK:
+       case MEMSETBADBLOCK:
+               tprints(", ");
+               print_loff_t(tcp, arg);
+               break;
+
+       case MEMGETINFO: {
+               struct mtd_info_user minfo;
+
+               if (entering(tcp))
                        return 0;
 
-               tprintf(", {offset=%#" PRIx32 ", erasesize=%#" PRIx32,
-                       rinfo.offset, rinfo.erasesize);
-               tprintf(", numblocks=%#" PRIx32 ", regionindex=%#" PRIx32 "}",
-                       rinfo.numblocks, rinfo.regionindex);
-               return 1;
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &minfo))
+                       break;
+
+               tprints("{type=");
+               printxval(mtd_type_options, minfo.type, "MTD_???");
+               tprints(", flags=");
+               printflags(mtd_flags_options, minfo.flags, "MTD_???");
+               tprintf(", size=%#" PRIx32 ", erasesize=%#" PRIx32,
+                       minfo.size, minfo.erasesize);
+               tprintf(", writesize=%#" PRIx32 ", oobsize=%#" PRIx32,
+                       minfo.writesize, minfo.oobsize);
+               tprintf(", padding=%#" PRIx64 "}",
+                       (uint64_t) minfo.padding);
+               break;
+       }
+
+       case MEMGETOOBSEL: {
+               struct nand_oobinfo ninfo;
+               unsigned int i;
 
-       case MEMGETOOBSEL:
-               if (!verbose(tcp) || umove(tcp, arg, &ninfo) < 0)
+               if (entering(tcp))
                        return 0;
 
-               tprints(", {useecc=");
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &ninfo))
+                       break;
+
+               tprints("{useecc=");
                printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???");
                tprintf(", eccbytes=%#" PRIx32, ninfo.eccbytes);
 
                tprints(", oobfree={");
                for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) {
+                       unsigned int j;
+
                        if (i)
                                tprints("}, ");
                        tprints("{");
@@ -159,22 +246,36 @@ mtd_ioctl(struct tcb *tcp, const unsigned int code, long arg)
                }
 
                tprints("}");
-               return 1;
+               break;
+       }
+
+       case OTPGETREGIONINFO: {
+               struct otp_info oinfo;
 
-       case OTPGETREGIONINFO:
-       case OTPLOCK:
-               if (!verbose(tcp) || umove(tcp, arg, &oinfo) < 0)
+               if (entering(tcp))
                        return 0;
 
-               tprintf(", {start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &oinfo))
+                       break;
+
+               tprintf("{start=%#" PRIx32 ", length=%#" PRIx32 ", locked=%" PRIu32 "}",
                        oinfo.start, oinfo.length, oinfo.locked);
-               return 1;
+               break;
+       }
 
-       case ECCGETLAYOUT:
-               if (!verbose(tcp) || umove(tcp, arg, &nlay) < 0)
+       case ECCGETLAYOUT: {
+               struct nand_ecclayout_user nlay;
+               unsigned int i;
+
+               if (entering(tcp))
                        return 0;
 
-               tprintf(", {eccbytes=%#" PRIx32 ", eccpos={", nlay.eccbytes);
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &nlay))
+                       break;
+
+               tprintf("{eccbytes=%#" PRIx32 ", eccpos={", nlay.eccbytes);
                for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) {
                        if (i)
                                tprints(", ");
@@ -188,117 +289,107 @@ mtd_ioctl(struct tcb *tcp, const unsigned int code, long arg)
                                nlay.oobfree[i].offset, nlay.oobfree[i].length);
                }
                tprints("}");
-               return 1;
+               break;
+       }
+
+       case ECCGETSTATS: {
+               struct mtd_ecc_stats estat;
 
-       case ECCGETSTATS:
-               if (!verbose(tcp) || umove(tcp, arg, &estat) < 0)
+               if (entering(tcp))
                        return 0;
 
-               tprintf(", {corrected=%#" PRIx32 ", failed=%#" PRIx32,
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &estat))
+                       break;
+
+               tprintf("{corrected=%#" PRIx32 ", failed=%#" PRIx32,
                        estat.corrected, estat.failed);
                tprintf(", badblocks=%#" PRIx32 ", bbtblocks=%#" PRIx32 "}",
                        estat.badblocks, estat.bbtblocks);
-               return 1;
-
-       case MEMWRITE:
-               if (!verbose(tcp) || umove(tcp, arg, &mreq) < 0)
-                       return 0;
-
-               tprintf(", {start=%#" PRIx64 ", len=%#" PRIx64,
-                       (uint64_t) mreq.start, (uint64_t) mreq.len);
-               tprintf(", ooblen=%#" PRIx64 ", usr_data=%#" PRIx64,
-                       (uint64_t) mreq.ooblen, (uint64_t) mreq.usr_data);
-               tprintf(", usr_oob=%#" PRIx64 ", mode=",
-                       (uint64_t) mreq.usr_oob);
-               printxval(mtd_mode_options, mreq.mode, "MTD_OPS_???");
-               tprints(", padding=...}");
-               return 1;
-
-       case OTPSELECT:
-               if (!verbose(tcp) || umove(tcp, arg, &i) < 0)
-                       return 0;
-
-               tprints(", [");
-               printxval(mtd_otp_options, i, "MTD_OTP_???");
-               tprints("]");
-               return 1;
+               break;
+       }
 
-       case MEMGETBADBLOCK:
-       case MEMSETBADBLOCK:
-               if (!verbose(tcp))
+       case OTPGETREGIONCOUNT:
+               if (entering(tcp))
                        return 0;
 
                tprints(", ");
-               print_loff_t(tcp, arg);
-               return 1;
+               printnum_int(tcp, arg, "%u");
+               break;
 
-       case OTPGETREGIONCOUNT:
-               if (!verbose(tcp) || umove(tcp, arg, &i) < 0)
+       case MEMGETREGIONCOUNT:
+               if (entering(tcp))
                        return 0;
 
-               tprintf(", [%u]", i);
-               return 1;
-
-       case MTDFILEMODE:
-               /* XXX: process return value as enum mtd_file_modes */
-
-       case MEMGETREGIONCOUNT:
-               /* These ones take simple args, so let default printer handle it */
+               tprints(", ");
+               printnum_int(tcp, arg, "%d");
+               break;
 
        default:
-               return 0;
+               return RVAL_DECODED;
        }
+
+       return RVAL_DECODED | 1;
 }
 
 #include "xlat/ubi_volume_types.h"
 #include "xlat/ubi_volume_props.h"
 
 int
-ubi_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+ubi_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
 {
-       struct ubi_mkvol_req mkvol;
-       struct ubi_rsvol_req rsvol;
-       struct ubi_rnvol_req rnvol;
-       struct ubi_attach_req attach;
-       struct ubi_map_req map;
-       struct ubi_set_vol_prop_req prop;
-
-       if (entering(tcp))
-               return 0;
+       if (!verbose(tcp))
+               return RVAL_DECODED;
 
        switch (code) {
        case UBI_IOCMKVOL:
-               if (!verbose(tcp) || umove(tcp, arg, &mkvol) < 0)
-                       return 0;
-
-               tprintf(", {vol_id=%" PRIi32 ", alignment=%" PRIi32
-                       ", bytes=%" PRIi64 ", vol_type=", mkvol.vol_id,
-                       mkvol.alignment, (int64_t)mkvol.bytes);
-               printxval(ubi_volume_types, mkvol.vol_type, "UBI_???_VOLUME");
-               tprintf(", name_len=%" PRIi16 ", name=", mkvol.name_len);
-               if (print_quoted_string(mkvol.name,
-                               CLAMP(mkvol.name_len, 0, UBI_MAX_VOLUME_NAME),
-                               QUOTE_0_TERMINATED) > 0) {
-                       tprints("...");
+               if (entering(tcp)) {
+                       struct ubi_mkvol_req mkvol;
+
+                       tprints(", ");
+                       if (umove_or_printaddr(tcp, arg, &mkvol))
+                               break;
+
+                       tprintf("{vol_id=%" PRIi32 ", alignment=%" PRIi32
+                               ", bytes=%" PRIi64 ", vol_type=", mkvol.vol_id,
+                               mkvol.alignment, (int64_t)mkvol.bytes);
+                       printxval(ubi_volume_types, mkvol.vol_type, "UBI_???_VOLUME");
+                       tprintf(", name_len=%" PRIi16 ", name=", mkvol.name_len);
+                       if (print_quoted_string(mkvol.name,
+                                       CLAMP(mkvol.name_len, 0, UBI_MAX_VOLUME_NAME),
+                                       QUOTE_0_TERMINATED) > 0) {
+                               tprints("...");
+                       }
+                       tprints("}");
+                       return 1;
                }
-               tprints("}");
-               return 1;
+               if (!syserror(tcp)) {
+                       tprints(" => ");
+                       printnum_int(tcp, arg, "%d");
+               }
+               break;
 
-       case UBI_IOCRSVOL:
-               if (!verbose(tcp) || umove(tcp, arg, &rsvol) < 0)
-                       return 0;
+       case UBI_IOCRSVOL: {
+               struct ubi_rsvol_req rsvol;
+
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &rsvol))
+                       break;
 
-               tprintf("{vol_id=%" PRIi32 ", bytes=%" PRIi64 "}",
+               tprintf("{vol_id=%" PRIi32 ", bytes=%" PRIi64 "}",
                        rsvol.vol_id, (int64_t)rsvol.bytes);
-               return 1;
+               break;
+       }
 
        case UBI_IOCRNVOL: {
-               __s32 c;
+               struct ubi_rnvol_req rnvol;
+               int c;
 
-               if (!verbose(tcp) || umove(tcp, arg, &rnvol) < 0)
-                       return 0;
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &rnvol))
+                       break;
 
-               tprintf("{count=%" PRIi32 ", ents=[", rnvol.count);
+               tprintf("{count=%" PRIi32 ", ents=[", rnvol.count);
                for (c = 0; c < CLAMP(rnvol.count, 0, UBI_MAX_RNVOL); ++c) {
                        if (c)
                                tprints(", ");
@@ -313,56 +404,89 @@ ubi_ioctl(struct tcb *tcp, const unsigned int code, long arg)
                        tprints("}");
                }
                tprints("]}");
-               return 1;
+               break;
        }
 
-       case UBI_IOCVOLUP: {
-               __s64 bytes;
+       case UBI_IOCEBCH: {
+               struct ubi_leb_change_req leb;
 
-               if (!verbose(tcp) || umove(tcp, arg, &bytes) < 0)
-                       return 0;
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &leb))
+                       break;
 
-               tprintf(", %" PRIi64, (int64_t)bytes);
-               return 1;
+               tprintf("{lnum=%d, bytes=%d}", leb.lnum, leb.bytes);
+               break;
        }
 
        case UBI_IOCATT:
-               if (!verbose(tcp) || umove(tcp, arg, &attach) < 0)
-                       return 0;
+               if (entering(tcp)) {
+                       struct ubi_attach_req attach;
+
+                       tprints(", ");
+                       if (umove_or_printaddr(tcp, arg, &attach))
+                               break;
+
+                       tprintf("{ubi_num=%" PRIi32 ", mtd_num=%" PRIi32
+                               ", vid_hdr_offset=%" PRIi32
+                               ", max_beb_per1024=%" PRIi16 "}",
+                               attach.ubi_num, attach.mtd_num,
+                               attach.vid_hdr_offset, attach.max_beb_per1024);
+                       return 1;
+               }
+               if (!syserror(tcp)) {
+                       tprints(" => ");
+                       printnum_int(tcp, arg, "%d");
+               }
+               break;
 
-               tprintf(", {ubi_num=%" PRIi32 ", mtd_num=%" PRIi32
-                       ", vid_hdr_offset=%" PRIi32
-                       ", max_beb_per1024=%" PRIi16 "}",
-                       attach.ubi_num, attach.mtd_num,
-                       attach.vid_hdr_offset, attach.max_beb_per1024);
-               return 1;
+       case UBI_IOCEBMAP: {
+               struct ubi_map_req map;
 
-       case UBI_IOCEBMAP:
-               if (!verbose(tcp) || umove(tcp, arg, &map) < 0)
-                       return 0;
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &map))
+                       break;
 
-               tprintf("{lnum=%" PRIi32 ", dtype=%" PRIi8 "}",
+               tprintf("{lnum=%" PRIi32 ", dtype=%" PRIi8 "}",
                        map.lnum, map.dtype);
-               return 1;
+               break;
+       }
 
-       case UBI_IOCSETVOLPROP:
-               if (!verbose(tcp) || umove(tcp, arg, &prop) < 0)
-                       return 0;
+       case UBI_IOCSETVOLPROP: {
+               struct ubi_set_vol_prop_req prop;
 
-               tprints(", {property=");
+               tprints(", ");
+               if (umove_or_printaddr(tcp, arg, &prop))
+                       break;
+
+               tprints("{property=");
                printxval(ubi_volume_props, prop.property, "UBI_VOL_PROP_???");
                tprintf(", value=%#" PRIx64 "}", (uint64_t)prop.value);
-               return 1;
+               break;
+       }
+
+
+       case UBI_IOCVOLUP:
+               tprints(", ");
+               printnum_int64(tcp, arg, "%" PRIi64);
+               break;
 
-       case UBI_IOCRMVOL:
        case UBI_IOCDET:
        case UBI_IOCEBER:
-       case UBI_IOCEBCH:
-       case UBI_IOCEBUNMAP:
        case UBI_IOCEBISMAP:
-               /* These ones take simple args, so let default printer handle it */
+       case UBI_IOCEBUNMAP:
+       case UBI_IOCRMVOL:
+               tprints(", ");
+               printnum_int(tcp, arg, "%d");
+               break;
+
+       case UBI_IOCVOLCRBLK:
+       case UBI_IOCVOLRMBLK:
+               /* no arguments */
+               break;
 
        default:
-               return 0;
+               return RVAL_DECODED;
        }
+
+       return RVAL_DECODED | 1;
 }
diff --git a/xlat/mtd_file_mode_options.in b/xlat/mtd_file_mode_options.in
new file mode 100644 (file)
index 0000000..d9e21ad
--- /dev/null
@@ -0,0 +1,5 @@
+#unconditional
+MTD_FILE_MODE_NORMAL
+MTD_FILE_MODE_OTP_FACTORY
+MTD_FILE_MODE_OTP_USER
+MTD_FILE_MODE_RAW