aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorFilip Bozuta <Filip.Bozuta@syrmia.com>2020-08-11 18:45:53 +0200
committerLaurent Vivier <laurent@vivier.eu>2020-08-27 12:29:50 +0200
commit1a674adf983204cfa5b5cc35185f2bf3274992c6 (patch)
tree9f7547eff32eed0415b26ef3beb5ffd8ad2f76b0 /linux-user
parent45f567994c2f0272cede9956ed0ea0d8a6294495 (diff)
downloadqemu-1a674adf983204cfa5b5cc35185f2bf3274992c6.zip
qemu-1a674adf983204cfa5b5cc35185f2bf3274992c6.tar.gz
qemu-1a674adf983204cfa5b5cc35185f2bf3274992c6.tar.bz2
linux-user: Add strace support for printing arguments of some clock and time functions
This patch implements strace argument printing functionality for following syscalls: * clock_getres, clock_gettime, clock_settime - clock and time functions int clock_getres(clockid_t clockid, struct timespec *res) int clock_gettime(clockid_t clockid, struct timespec *tp) int clock_settime(clockid_t clockid, const struct timespec *tp) man page: https://man7.org/linux/man-pages/man2/clock_getres.2.html * gettimeofday - get time int gettimeofday(struct timeval *tv, struct timezone *tz) man page: https://man7.org/linux/man-pages/man2/gettimeofday.2.html * getitimer, setitimer - get or set value of an interval timer int getitimer(int which, struct itimerval *curr_value) int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value) man page: https://man7.org/linux/man-pages/man2/getitimer.2.html Implementation notes: All of the syscalls have some structue types as argument types and thus a separate printing function was stated in file "strace.list" for each of them. All of these functions use existing functions for their appropriate structure types ("print_timeval()" and "print_timezone()"). Functions "print_timespec()" and "print_itimerval()" were added in this patch so that they can be used to print types "struct timespec" and "struct itimerval" used by some of the syscalls. Function "print_itimerval()" uses the existing function "print_timeval()" to print fields of the structure "struct itimerval" that are of type "struct timeval". Function "print_enums()", which was introduced in the previous patch, is used to print the interval timer type which is the first argument of "getitimer()" and "setitimer()". Also, this function is used to print the clock id which is the first argument of "clock_getres()" and "clock_gettime()". For that reason, the existing function "print_clockid()" was removed in this patch. Existing function "print_clock_adjtime()" was also changed for this reason to use "print_enums()". The existing function "print_timeval()" was changed a little so that it prints the field names beside the values. Syscalls "clock_getres()" and "clock_gettime()" have the same number and types of arguments and thus their print functions "print_clock_getres" and "print_clock_gettime" share a common definition in file "strace.c". Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20200811164553.27713-6-Filip.Bozuta@syrmia.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/strace.c287
-rw-r--r--linux-user/strace.list17
2 files changed, 232 insertions, 72 deletions
diff --git a/linux-user/strace.c b/linux-user/strace.c
index d0731b8..c7ef948 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -78,7 +78,9 @@ UNUSED static void print_string(abi_long, int);
UNUSED static void print_buf(abi_long addr, abi_long len, int last);
UNUSED static void print_raw_param(const char *, abi_long, int);
UNUSED static void print_timeval(abi_ulong, int);
+UNUSED static void print_timespec(abi_ulong, int);
UNUSED static void print_timezone(abi_ulong, int);
+UNUSED static void print_itimerval(abi_ulong, int);
UNUSED static void print_number(abi_long, int);
UNUSED static void print_signal(abi_ulong, int);
UNUSED static void print_sockaddr(abi_ulong, abi_long, int);
@@ -582,69 +584,6 @@ print_fdset(int n, abi_ulong target_fds_addr)
}
#endif
-#ifdef TARGET_NR_clock_adjtime
-/* IDs of the various system clocks */
-#define TARGET_CLOCK_REALTIME 0
-#define TARGET_CLOCK_MONOTONIC 1
-#define TARGET_CLOCK_PROCESS_CPUTIME_ID 2
-#define TARGET_CLOCK_THREAD_CPUTIME_ID 3
-#define TARGET_CLOCK_MONOTONIC_RAW 4
-#define TARGET_CLOCK_REALTIME_COARSE 5
-#define TARGET_CLOCK_MONOTONIC_COARSE 6
-#define TARGET_CLOCK_BOOTTIME 7
-#define TARGET_CLOCK_REALTIME_ALARM 8
-#define TARGET_CLOCK_BOOTTIME_ALARM 9
-#define TARGET_CLOCK_SGI_CYCLE 10
-#define TARGET_CLOCK_TAI 11
-
-static void
-print_clockid(int clockid, int last)
-{
- switch (clockid) {
- case TARGET_CLOCK_REALTIME:
- qemu_log("CLOCK_REALTIME");
- break;
- case TARGET_CLOCK_MONOTONIC:
- qemu_log("CLOCK_MONOTONIC");
- break;
- case TARGET_CLOCK_PROCESS_CPUTIME_ID:
- qemu_log("CLOCK_PROCESS_CPUTIME_ID");
- break;
- case TARGET_CLOCK_THREAD_CPUTIME_ID:
- qemu_log("CLOCK_THREAD_CPUTIME_ID");
- break;
- case TARGET_CLOCK_MONOTONIC_RAW:
- qemu_log("CLOCK_MONOTONIC_RAW");
- break;
- case TARGET_CLOCK_REALTIME_COARSE:
- qemu_log("CLOCK_REALTIME_COARSE");
- break;
- case TARGET_CLOCK_MONOTONIC_COARSE:
- qemu_log("CLOCK_MONOTONIC_COARSE");
- break;
- case TARGET_CLOCK_BOOTTIME:
- qemu_log("CLOCK_BOOTTIME");
- break;
- case TARGET_CLOCK_REALTIME_ALARM:
- qemu_log("CLOCK_REALTIME_ALARM");
- break;
- case TARGET_CLOCK_BOOTTIME_ALARM:
- qemu_log("CLOCK_BOOTTIME_ALARM");
- break;
- case TARGET_CLOCK_SGI_CYCLE:
- qemu_log("CLOCK_SGI_CYCLE");
- break;
- case TARGET_CLOCK_TAI:
- qemu_log("CLOCK_TAI");
- break;
- default:
- qemu_log("%d", clockid);
- break;
- }
- qemu_log("%s", get_comma(last));
-}
-#endif
-
/*
* Sysycall specific output functions
*/
@@ -843,6 +782,81 @@ print_syscall_ret_adjtimex(void *cpu_env, const struct syscallname *name,
}
#endif
+#if defined(TARGET_NR_clock_gettime) || defined(TARGET_NR_clock_getres)
+static void
+print_syscall_ret_clock_gettime(void *cpu_env, 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)
+{
+ if (!print_syscall_err(ret)) {
+ qemu_log(TARGET_ABI_FMT_ld, ret);
+ qemu_log(" (");
+ print_timespec(arg1, 1);
+ qemu_log(")");
+ }
+
+ qemu_log("\n");
+}
+#define print_syscall_ret_clock_getres print_syscall_ret_clock_gettime
+#endif
+
+#ifdef TARGET_NR_gettimeofday
+static void
+print_syscall_ret_gettimeofday(void *cpu_env, 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)
+{
+ if (!print_syscall_err(ret)) {
+ qemu_log(TARGET_ABI_FMT_ld, ret);
+ qemu_log(" (");
+ print_timeval(arg0, 0);
+ print_timezone(arg1, 1);
+ qemu_log(")");
+ }
+
+ qemu_log("\n");
+}
+#endif
+
+#ifdef TARGET_NR_getitimer
+static void
+print_syscall_ret_getitimer(void *cpu_env, 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)
+{
+ if (!print_syscall_err(ret)) {
+ qemu_log(TARGET_ABI_FMT_ld, ret);
+ qemu_log(" (");
+ print_itimerval(arg1, 1);
+ qemu_log(")");
+ }
+
+ qemu_log("\n");
+}
+#endif
+
+
+#ifdef TARGET_NR_getitimer
+static void
+print_syscall_ret_setitimer(void *cpu_env, 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)
+{
+ if (!print_syscall_err(ret)) {
+ qemu_log(TARGET_ABI_FMT_ld, ret);
+ qemu_log(" (old_value = ");
+ print_itimerval(arg2, 1);
+ qemu_log(")");
+ }
+
+ qemu_log("\n");
+}
+#endif
+
#if defined(TARGET_NR_listxattr) || defined(TARGET_NR_llistxattr) \
|| defined(TARGGET_NR_flistxattr)
static void
@@ -1221,6 +1235,43 @@ UNUSED static struct flags mlockall_flags[] = {
FLAG_END,
};
+/* IDs of the various system clocks */
+#define TARGET_CLOCK_REALTIME 0
+#define TARGET_CLOCK_MONOTONIC 1
+#define TARGET_CLOCK_PROCESS_CPUTIME_ID 2
+#define TARGET_CLOCK_THREAD_CPUTIME_ID 3
+#define TARGET_CLOCK_MONOTONIC_RAW 4
+#define TARGET_CLOCK_REALTIME_COARSE 5
+#define TARGET_CLOCK_MONOTONIC_COARSE 6
+#define TARGET_CLOCK_BOOTTIME 7
+#define TARGET_CLOCK_REALTIME_ALARM 8
+#define TARGET_CLOCK_BOOTTIME_ALARM 9
+#define TARGET_CLOCK_SGI_CYCLE 10
+#define TARGET_CLOCK_TAI 11
+
+UNUSED static struct enums clockids[] = {
+ ENUM_TARGET(CLOCK_REALTIME),
+ ENUM_TARGET(CLOCK_MONOTONIC),
+ ENUM_TARGET(CLOCK_PROCESS_CPUTIME_ID),
+ ENUM_TARGET(CLOCK_THREAD_CPUTIME_ID),
+ ENUM_TARGET(CLOCK_MONOTONIC_RAW),
+ ENUM_TARGET(CLOCK_REALTIME_COARSE),
+ ENUM_TARGET(CLOCK_MONOTONIC_COARSE),
+ ENUM_TARGET(CLOCK_BOOTTIME),
+ ENUM_TARGET(CLOCK_REALTIME_ALARM),
+ ENUM_TARGET(CLOCK_BOOTTIME_ALARM),
+ ENUM_TARGET(CLOCK_SGI_CYCLE),
+ ENUM_TARGET(CLOCK_TAI),
+ ENUM_END,
+};
+
+UNUSED static struct enums itimer_types[] = {
+ ENUM_GENERIC(ITIMER_REAL),
+ ENUM_GENERIC(ITIMER_VIRTUAL),
+ ENUM_GENERIC(ITIMER_PROF),
+ ENUM_END,
+};
+
/*
* print_xxx utility functions. These are used to print syscall
* parameters in certain format. All of these have parameter
@@ -1439,14 +1490,35 @@ print_timeval(abi_ulong tv_addr, int last)
print_pointer(tv_addr, last);
return;
}
- qemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}%s",
- tswapal(tv->tv_sec), tswapal(tv->tv_usec), get_comma(last));
+ qemu_log("{tv_sec = " TARGET_ABI_FMT_ld
+ ",tv_usec = " TARGET_ABI_FMT_ld "}%s",
+ tswapal(tv->tv_sec), tswapal(tv->tv_usec), get_comma(last));
unlock_user(tv, tv_addr, 0);
} else
qemu_log("NULL%s", get_comma(last));
}
static void
+print_timespec(abi_ulong ts_addr, int last)
+{
+ if (ts_addr) {
+ struct target_timespec *ts;
+
+ ts = lock_user(VERIFY_READ, ts_addr, sizeof(*ts), 1);
+ if (!ts) {
+ print_pointer(ts_addr, last);
+ return;
+ }
+ qemu_log("{tv_sec = " TARGET_ABI_FMT_ld
+ ",tv_nsec = " TARGET_ABI_FMT_ld "}%s",
+ tswapal(ts->tv_sec), tswapal(ts->tv_nsec), get_comma(last));
+ unlock_user(ts, ts_addr, 0);
+ } else {
+ qemu_log("NULL%s", get_comma(last));
+ }
+}
+
+static void
print_timezone(abi_ulong tz_addr, int last)
{
if (tz_addr) {
@@ -1465,6 +1537,22 @@ print_timezone(abi_ulong tz_addr, int last)
}
}
+static void
+print_itimerval(abi_ulong it_addr, int last)
+{
+ if (it_addr) {
+ qemu_log("{it_interval=");
+ print_timeval(it_addr +
+ offsetof(struct target_itimerval, it_interval), 0);
+ qemu_log("it_value=");
+ print_timeval(it_addr +
+ offsetof(struct target_itimerval, it_value), 0);
+ qemu_log("}%s", get_comma(last));
+ } else {
+ qemu_log("NULL%s", get_comma(last));
+ }
+}
+
#undef UNUSED
#ifdef TARGET_NR_accept
@@ -1577,7 +1665,7 @@ print_clock_adjtime(void *cpu_env, const struct syscallname *name,
abi_long arg3, abi_long arg4, abi_long arg5)
{
print_syscall_prologue(name);
- print_clockid(arg0, 0);
+ print_enums(clockids, arg0, 0);
print_pointer(arg1, 1);
print_syscall_epilogue(name);
}
@@ -1907,6 +1995,19 @@ print_futimesat(void *cpu_env, const struct syscallname *name,
}
#endif
+#ifdef TARGET_NR_gettimeofday
+static void
+print_gettimeofday(void *cpu_env, 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_pointer(arg0, 0);
+ print_pointer(arg1, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
#ifdef TARGET_NR_settimeofday
static void
print_settimeofday(void *cpu_env, const struct syscallname *name,
@@ -1920,6 +2021,60 @@ print_settimeofday(void *cpu_env, const struct syscallname *name,
}
#endif
+#if defined(TARGET_NR_clock_gettime) || defined(TARGET_NR_clock_getres)
+static void
+print_clock_gettime(void *cpu_env, 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_enums(clockids, arg0, 0);
+ print_pointer(arg1, 1);
+ print_syscall_epilogue(name);
+}
+#define print_clock_getres print_clock_gettime
+#endif
+
+#ifdef TARGET_NR_clock_settime
+static void
+print_clock_settime(void *cpu_env, 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_enums(clockids, arg0, 0);
+ print_timespec(arg1, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
+#ifdef TARGET_NR_getitimer
+static void
+print_getitimer(void *cpu_env, 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_enums(itimer_types, arg0, 0);
+ print_pointer(arg1, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
+#ifdef TARGET_NR_setitimer
+static void
+print_setitimer(void *cpu_env, 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_enums(itimer_types, arg0, 0);
+ print_itimerval(arg1, 0);
+ print_pointer(arg2, 1);
+ print_syscall_epilogue(name);
+}
+#endif
+
#ifdef TARGET_NR_link
static void
print_link(void *cpu_env, const struct syscallname *name,
diff --git a/linux-user/strace.list b/linux-user/strace.list
index d0ea7f3..084048a 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -83,16 +83,18 @@
{ TARGET_NR_clock_adjtime, "clock_adjtime" , NULL, print_clock_adjtime, NULL },
#endif
#ifdef TARGET_NR_clock_getres
-{ TARGET_NR_clock_getres, "clock_getres" , NULL, NULL, NULL },
+{ TARGET_NR_clock_getres, "clock_getres" , NULL, print_clock_getres,
+ print_syscall_ret_clock_getres },
#endif
#ifdef TARGET_NR_clock_gettime
-{ TARGET_NR_clock_gettime, "clock_gettime" , NULL, NULL, NULL },
+{ TARGET_NR_clock_gettime, "clock_gettime" , NULL, print_clock_gettime,
+ print_syscall_ret_clock_gettime },
#endif
#ifdef TARGET_NR_clock_nanosleep
{ TARGET_NR_clock_nanosleep, "clock_nanosleep" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_clock_settime
-{ TARGET_NR_clock_settime, "clock_settime" , NULL, NULL, NULL },
+{ TARGET_NR_clock_settime, "clock_settime" , NULL, print_clock_settime, NULL },
#endif
#ifdef TARGET_NR_clone
{ TARGET_NR_clone, "clone" , NULL, print_clone, NULL },
@@ -315,7 +317,8 @@
{ TARGET_NR_gethostname, "gethostname" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_getitimer
-{ TARGET_NR_getitimer, "getitimer" , NULL, NULL, NULL },
+{ TARGET_NR_getitimer, "getitimer" , NULL, print_getitimer,
+ print_syscall_ret_getitimer },
#endif
#ifdef TARGET_NR_get_kernel_syms
{ TARGET_NR_get_kernel_syms, "get_kernel_syms" , NULL, NULL, NULL },
@@ -388,7 +391,8 @@
{ TARGET_NR_gettid, "gettid" , "%s()", NULL, NULL },
#endif
#ifdef TARGET_NR_gettimeofday
-{ TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL },
+{ TARGET_NR_gettimeofday, "gettimeofday" , NULL, print_gettimeofday,
+ print_syscall_ret_gettimeofday },
#endif
#ifdef TARGET_NR_getuid
{ TARGET_NR_getuid, "getuid" , "%s()", NULL, NULL },
@@ -1291,7 +1295,8 @@
{ TARGET_NR_sethostname, "sethostname" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_setitimer
-{ TARGET_NR_setitimer, "setitimer" , NULL, NULL, NULL },
+{ TARGET_NR_setitimer, "setitimer" , NULL, print_setitimer,
+ print_syscall_ret_setitimer },
#endif
#ifdef TARGET_NR_set_mempolicy
{ TARGET_NR_set_mempolicy, "set_mempolicy" , NULL, NULL, NULL },