summaryrefslogtreecommitdiffstats
path: root/linux-user
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/qemu.h20
-rw-r--r--linux-user/strace.c107
-rw-r--r--linux-user/strace.list3
-rw-r--r--linux-user/syscall.c20
4 files changed, 130 insertions, 20 deletions
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index be67391ba4..5c964389c1 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -184,6 +184,26 @@ struct linux_binprm {
int (*core_dump)(int, const CPUArchState *); /* coredump routine */
};
+typedef struct IOCTLEntry IOCTLEntry;
+
+typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg);
+
+struct IOCTLEntry {
+ int target_cmd;
+ unsigned int host_cmd;
+ const char *name;
+ int access;
+ do_ioctl_fn *do_ioctl;
+ const argtype arg_type[5];
+};
+
+extern IOCTLEntry ioctl_entries[];
+
+#define IOC_R 0x0001
+#define IOC_W 0x0002
+#define IOC_RW (IOC_R | IOC_W)
+
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
abi_ulong stringp, int push_ptr);
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 32e5e987ac..5235b2260c 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -860,6 +860,44 @@ print_syscall_ret_listxattr(const struct syscallname *name, abi_long ret,
#define print_syscall_ret_flistxattr print_syscall_ret_listxattr
#endif
+#ifdef TARGET_NR_ioctl
+static void
+print_syscall_ret_ioctl(const struct syscallname *name, abi_long ret,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_err(ret);
+
+ if (ret >= 0) {
+ qemu_log(TARGET_ABI_FMT_ld, ret);
+
+ const IOCTLEntry *ie;
+ const argtype *arg_type;
+ void *argptr;
+ int target_size;
+
+ for (ie = ioctl_entries; ie->target_cmd != 0; ie++) {
+ if (ie->target_cmd == arg1) {
+ break;
+ }
+ }
+
+ if (ie->target_cmd == arg1 &&
+ (ie->access == IOC_R || ie->access == IOC_RW)) {
+ arg_type = ie->arg_type;
+ qemu_log(" (");
+ arg_type++;
+ target_size = thunk_type_size(arg_type, 0);
+ argptr = lock_user(VERIFY_READ, arg2, target_size, 1);
+ thunk_print(argptr, arg_type);
+ unlock_user(argptr, arg2, target_size);
+ qemu_log(")");
+ }
+ }
+ qemu_log("\n");
+}
+#endif
+
UNUSED static struct flags access_flags[] = {
FLAG_GENERIC(F_OK),
FLAG_GENERIC(R_OK),
@@ -3026,6 +3064,75 @@ print_statx(const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_ioctl
+static void
+print_ioctl(const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ print_syscall_prologue(name);
+ print_raw_param("%d", arg0, 0);
+
+ const IOCTLEntry *ie;
+ const argtype *arg_type;
+ void *argptr;
+ int target_size;
+
+ for (ie = ioctl_entries; ie->target_cmd != 0; ie++) {
+ if (ie->target_cmd == arg1) {
+ break;
+ }
+ }
+
+ if (ie->target_cmd == 0) {
+ print_raw_param("%#x", arg1, 0);
+ print_raw_param("%#x", arg2, 1);
+ } else {
+ qemu_log("%s", ie->name);
+ arg_type = ie->arg_type;
+
+ if (arg_type[0] != TYPE_NULL) {
+ qemu_log(",");
+
+ switch (arg_type[0]) {
+ case TYPE_PTRVOID:
+ print_pointer(arg2, 1);
+ break;
+ case TYPE_CHAR:
+ case TYPE_SHORT:
+ case TYPE_INT:
+ print_raw_param("%d", arg2, 1);
+ break;
+ case TYPE_LONG:
+ print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
+ break;
+ case TYPE_ULONG:
+ print_raw_param(TARGET_ABI_FMT_lu, arg2, 1);
+ break;
+ case TYPE_PTR:
+ switch (ie->access) {
+ case IOC_R:
+ print_pointer(arg2, 1);
+ break;
+ case IOC_W:
+ case IOC_RW:
+ arg_type++;
+ target_size = thunk_type_size(arg_type, 0);
+ argptr = lock_user(VERIFY_READ, arg2, target_size, 1);
+ thunk_print(argptr, arg_type);
+ unlock_user(argptr, arg2, target_size);
+ break;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+ }
+ print_syscall_epilogue(name);
+}
+#endif
+
/*
* An array of all of the syscalls we know about
*/
diff --git a/linux-user/strace.list b/linux-user/strace.list
index ebb713252c..a04706a524 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -433,7 +433,8 @@
{ TARGET_NR_io_cancel, "io_cancel" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_ioctl
-{ TARGET_NR_ioctl, "ioctl" , "%s(%d,%#x,%#x)", NULL, NULL },
+{ TARGET_NR_ioctl, "ioctl" , NULL, print_ioctl,
+ print_syscall_ret_ioctl},
#endif
#ifdef TARGET_NR_io_destroy
{ TARGET_NR_io_destroy, "io_destroy" , NULL, NULL, NULL },
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 506b94a12c..82afadcea0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4481,24 +4481,6 @@ STRUCT_MAX
#undef STRUCT
#undef STRUCT_SPECIAL
-typedef struct IOCTLEntry IOCTLEntry;
-
-typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
- int fd, int cmd, abi_long arg);
-
-struct IOCTLEntry {
- int target_cmd;
- unsigned int host_cmd;
- const char *name;
- int access;
- do_ioctl_fn *do_ioctl;
- const argtype arg_type[5];
-};
-
-#define IOC_R 0x0001
-#define IOC_W 0x0002
-#define IOC_RW (IOC_R | IOC_W)
-
#define MAX_STRUCT_SIZE 4096
#ifdef CONFIG_FIEMAP
@@ -5374,7 +5356,7 @@ static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
#endif
-static IOCTLEntry ioctl_entries[] = {
+IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
#define IOCTL_SPECIAL(cmd, access, dofn, ...) \