qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] linux-user: Add strace support for printing arguments for ioctls


From: Filip Bozuta
Subject: [PATCH] linux-user: Add strace support for printing arguments for ioctls used for terminals and serial lines
Date: Tue, 14 Jul 2020 22:04:38 +0200

Functions "print_ioctl()" and "print_syscall_ret_ioctl()" are used
to print arguments of "ioctl()" with "-strace". These functions
use "thunk_print()", which is defined in "thunk.c", to print the
contents of ioctl's third arguments that are not basic types.
However, this function doesn't handle ioctls of group ioctl_tty which
are used for terminals and serial lines. These ioctls use a type
"struct termios" which thunk type is defined in a non standard
way using "STRUCT_SPECIAL()". This means that this type is not decoded
regularly using "thunk_convert()" and uses special converting functions
"target_to_host_termios()" and "host_to_target_termios()", which are defined
in "syscall.c" to decode it's values. For simillar reasons, this type is
also not printed regularly using "thunk_print()". That is the reason
why a separate printing function "print_termios()" is defined in
file "strace.c". This function decodes and prints flag values of the
"termios" structure.

Implementation notes:

    Function "print_termios()" was implemented in "strace.c" using
    an existing function "print_flags()" to print flag values of
    "struct termios" fields. These flag values were defined
    using an existing macro "FLAG_TARGET()" that generates aproppriate
    target flag values and string representations of these flags.
    This function was declared in "qemu.h" so that it can be accessed
    in "syscall.c". Type "StructEntry" defined in "exec/user/thunk.h"
    contains information that is used to decode structure values.
    Field "void print(void *arg)" was added in this structure as a
    special print function. Also, function "thunk_print()" was changed
    a little so that it uses this special print function in case
    it is defined. This printing function was instantiated with the
    defined "print_termios()" in "syscall.c" in "struct_termios_def".

Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com>
---
 include/exec/user/thunk.h |   1 +
 linux-user/qemu.h         |   2 +
 linux-user/strace.c       | 193 ++++++++++++++++++++++++++++++++++++++
 linux-user/syscall.c      |   1 +
 thunk.c                   |  23 +++--
 5 files changed, 211 insertions(+), 9 deletions(-)

diff --git a/include/exec/user/thunk.h b/include/exec/user/thunk.h
index 7992475c9f..a5bbb2c733 100644
--- a/include/exec/user/thunk.h
+++ b/include/exec/user/thunk.h
@@ -55,6 +55,7 @@ typedef struct {
     int *field_offsets[2];
     /* special handling */
     void (*convert[2])(void *dst, const void *src);
+    void (*print)(void *arg);
     int size[2];
     int align[2];
     const char *name;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 5c964389c1..e51a0ededb 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -706,6 +706,8 @@ static inline uint64_t target_offset64(uint64_t word0, 
uint64_t word1)
 }
 #endif /* TARGET_ABI_BITS != 32 */
 
+extern void print_termios(void *arg);
+
 /**
  * preexit_cleanup: housekeeping before the guest exits
  *
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 5235b2260c..7b5408cf4a 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1193,6 +1193,138 @@ UNUSED static struct flags falloc_flags[] = {
 #endif
 };
 
+UNUSED static struct flags termios_iflags[] = {
+    FLAG_TARGET(IGNBRK),
+    FLAG_TARGET(BRKINT),
+    FLAG_TARGET(IGNPAR),
+    FLAG_TARGET(PARMRK),
+    FLAG_TARGET(INPCK),
+    FLAG_TARGET(ISTRIP),
+    FLAG_TARGET(INLCR),
+    FLAG_TARGET(IGNCR),
+    FLAG_TARGET(ICRNL),
+    FLAG_TARGET(IUCLC),
+    FLAG_TARGET(IXON),
+    FLAG_TARGET(IXANY),
+    FLAG_TARGET(IXOFF),
+    FLAG_TARGET(IMAXBEL),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_oflags[] = {
+    FLAG_TARGET(OPOST),
+    FLAG_TARGET(OLCUC),
+    FLAG_TARGET(ONLCR),
+    FLAG_TARGET(OCRNL),
+    FLAG_TARGET(ONOCR),
+    FLAG_TARGET(ONLRET),
+    FLAG_TARGET(OFILL),
+    FLAG_TARGET(OFDEL),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_oflags_NLDLY[] = {
+    FLAG_TARGET(NL0),
+    FLAG_TARGET(NL1),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_oflags_CRDLY[] = {
+    FLAG_TARGET(CR0),
+    FLAG_TARGET(CR1),
+    FLAG_TARGET(CR2),
+    FLAG_TARGET(CR3),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_oflags_TABDLY[] = {
+    FLAG_TARGET(TAB0),
+    FLAG_TARGET(TAB1),
+    FLAG_TARGET(TAB2),
+    FLAG_TARGET(TAB3),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_oflags_VTDLY[] = {
+    FLAG_TARGET(VT0),
+    FLAG_TARGET(VT1),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_oflags_FFDLY[] = {
+    FLAG_TARGET(FF0),
+    FLAG_TARGET(FF1),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_oflags_BSDLY[] = {
+    FLAG_TARGET(BS0),
+    FLAG_TARGET(BS1),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_cflags_CBAUD[] = {
+    FLAG_TARGET(B0),
+    FLAG_TARGET(B50),
+    FLAG_TARGET(B75),
+    FLAG_TARGET(B110),
+    FLAG_TARGET(B134),
+    FLAG_TARGET(B150),
+    FLAG_TARGET(B200),
+    FLAG_TARGET(B300),
+    FLAG_TARGET(B600),
+    FLAG_TARGET(B1200),
+    FLAG_TARGET(B1800),
+    FLAG_TARGET(B2400),
+    FLAG_TARGET(B4800),
+    FLAG_TARGET(B9600),
+    FLAG_TARGET(B19200),
+    FLAG_TARGET(B38400),
+    FLAG_TARGET(B57600),
+    FLAG_TARGET(B115200),
+    FLAG_TARGET(B230400),
+    FLAG_TARGET(B460800),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_cflags_CSIZE[] = {
+    FLAG_TARGET(CS5),
+    FLAG_TARGET(CS6),
+    FLAG_TARGET(CS7),
+    FLAG_TARGET(CS8),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_cflags[] = {
+    FLAG_TARGET(CSTOPB),
+    FLAG_TARGET(CREAD),
+    FLAG_TARGET(PARENB),
+    FLAG_TARGET(PARODD),
+    FLAG_TARGET(HUPCL),
+    FLAG_TARGET(CLOCAL),
+    FLAG_TARGET(CRTSCTS),
+    FLAG_END,
+};
+
+UNUSED static struct flags termios_lflags[] = {
+    FLAG_TARGET(ISIG),
+    FLAG_TARGET(ICANON),
+    FLAG_TARGET(XCASE),
+    FLAG_TARGET(ECHO),
+    FLAG_TARGET(ECHOE),
+    FLAG_TARGET(ECHOK),
+    FLAG_TARGET(ECHONL),
+    FLAG_TARGET(NOFLSH),
+    FLAG_TARGET(TOSTOP),
+    FLAG_TARGET(ECHOCTL),
+    FLAG_TARGET(ECHOPRT),
+    FLAG_TARGET(ECHOKE),
+    FLAG_TARGET(FLUSHO),
+    FLAG_TARGET(PENDIN),
+    FLAG_TARGET(IEXTEN),
+    FLAG_END,
+};
+
 /*
  * print_xxx utility functions.  These are used to print syscall
  * parameters in certain format.  All of these have parameter
@@ -1420,6 +1552,67 @@ print_timezone(abi_ulong tz_addr, int last)
     }
 }
 
+void
+print_termios(void *arg)
+{
+    const struct target_termios *target = arg;
+
+    abi_long iflags = tswap32(target->c_iflag);
+    abi_long oflags = tswap32(target->c_oflag);
+    abi_long cflags = tswap32(target->c_cflag);
+    abi_long lflags = tswap32(target->c_lflag);
+
+    qemu_log("{");
+
+    qemu_log("c_iflag = ");
+    print_flags(termios_iflags, iflags, 0);
+
+    qemu_log("c_oflag = ");
+    abi_long oflags_clean =  oflags & ~(TARGET_NLDLY) & ~(TARGET_CRDLY) &
+                                      ~(TARGET_TABDLY) & ~(TARGET_BSDLY) &
+                                      ~(TARGET_VTDLY) & ~(TARGET_FFDLY);
+    print_flags(termios_oflags, oflags_clean, 0);
+    if (oflags & TARGET_NLDLY) {
+        print_flags(termios_oflags_NLDLY, oflags & TARGET_NLDLY, 0);
+    }
+    if (oflags & TARGET_CRDLY) {
+        print_flags(termios_oflags_CRDLY, oflags & TARGET_CRDLY, 0);
+    }
+    if (oflags & TARGET_TABDLY) {
+        print_flags(termios_oflags_TABDLY, oflags & TARGET_TABDLY, 0);
+    }
+    if (oflags & TARGET_BSDLY) {
+        print_flags(termios_oflags_BSDLY, oflags & TARGET_BSDLY, 0);
+    }
+    if (oflags & TARGET_VTDLY) {
+        print_flags(termios_oflags_VTDLY, oflags & TARGET_VTDLY, 0);
+    }
+    if (oflags & TARGET_FFDLY) {
+        print_flags(termios_oflags_FFDLY, oflags & TARGET_FFDLY, 0);
+    }
+
+    qemu_log("c_cflag = ");
+    if (cflags & TARGET_CBAUD) {
+        print_flags(termios_cflags_CBAUD, cflags & TARGET_CBAUD, 0);
+    }
+    if (cflags & TARGET_CSIZE) {
+        print_flags(termios_cflags_CSIZE, cflags & TARGET_CSIZE, 0);
+    }
+    abi_long cflags_clean = cflags & ~(TARGET_CBAUD) & ~(TARGET_CSIZE);
+    print_flags(termios_cflags, cflags_clean, 0);
+
+    qemu_log("c_lflag = ");
+    print_flags(termios_lflags, lflags, 0);
+
+    qemu_log("c_cc = ");
+    qemu_log("\"%s\",", target->c_cc);
+
+    qemu_log("c_line = ");
+    print_raw_param("\'%c\'", target->c_line, 1);
+
+    qemu_log("}");
+}
+
 #undef UNUSED
 
 #ifdef TARGET_NR_accept
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 82afadcea0..0c79011727 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5633,6 +5633,7 @@ static const StructEntry struct_termios_def = {
     .convert = { host_to_target_termios, target_to_host_termios },
     .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
     .align = { __alignof__(struct target_termios), __alignof__(struct 
host_termios) },
+    .print = print_termios,
 };
 
 static bitmask_transtbl mmap_flags_tbl[] = {
diff --git a/thunk.c b/thunk.c
index c5d9719747..0718325d86 100644
--- a/thunk.c
+++ b/thunk.c
@@ -404,19 +404,24 @@ const argtype *thunk_print(void *arg, const argtype 
*type_ptr)
             const int *arg_offsets;
 
             se = struct_entries + *type_ptr++;
-            a = arg;
 
-            field_types = se->field_types;
-            arg_offsets = se->field_offsets[0];
+            if (se->print != NULL) {
+                se->print(arg);
+            } else {
+                a = arg;
 
-            qemu_log("{");
-            for (i = 0; i < se->nb_fields; i++) {
-                if (i > 0) {
-                    qemu_log(",");
+                field_types = se->field_types;
+                arg_offsets = se->field_offsets[0];
+
+                qemu_log("{");
+                for (i = 0; i < se->nb_fields; i++) {
+                    if (i > 0) {
+                        qemu_log(",");
+                    }
+                    field_types = thunk_print(a + arg_offsets[i], field_types);
                 }
-                field_types = thunk_print(a + arg_offsets[i], field_types);
+                qemu_log("}");
             }
-            qemu_log("}");
         }
         break;
     default:
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]