From f67026dda460948362aa91ec3b6cf9a521181f21 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 9 May 2019 22:03:30 +0000 Subject: [PATCH] Implement printers for kernel_timespec32_t They are going to be used to re-implement parsers of syscalls that deal with 32-bit timespec. * defs.h (print_timespec32_data_size, print_timespec32_array_data_size, print_timespec32, sprint_timespec32, print_timespec32_utime_pair, print_itimerspec32): New prototypes. * print_timespec.h: New file based on print_timespec.c. * print_timespec32.c: New file. * Makefile.am (strace_SOURCES): Add them. --- Makefile.am | 2 + defs.h | 11 ++++ print_timespec.h | 153 +++++++++++++++++++++++++++++++++++++++++++++ print_timespec32.c | 23 +++++++ 4 files changed, 189 insertions(+) create mode 100644 print_timespec.h create mode 100644 print_timespec32.c diff --git a/Makefile.am b/Makefile.am index 048e1229..3177b824 100644 --- a/Makefile.am +++ b/Makefile.am @@ -243,6 +243,8 @@ strace_SOURCES = \ print_struct_stat.c \ print_time.c \ print_timespec.c \ + print_timespec.h \ + print_timespec32.c \ print_timeval.c \ print_timex.c \ print_utils.h \ diff --git a/defs.h b/defs.h index 1a139f92..b723cb88 100644 --- a/defs.h +++ b/defs.h @@ -1109,6 +1109,17 @@ tprint_iov(struct tcb *tcp, kernel_ulong_t len, kernel_ulong_t addr, tprint_iov_upto(tcp, len, addr, decode_iov, -1); } +# if HAVE_ARCH_TIME32_SYSCALLS +extern bool print_timespec32_data_size(const void *arg, size_t size); +extern bool print_timespec32_array_data_size(const void *arg, + unsigned int nmemb, + size_t size); +extern int print_timespec32(struct tcb *, kernel_ulong_t); +extern const char *sprint_timespec32(struct tcb *, kernel_ulong_t); +extern int print_timespec32_utime_pair(struct tcb *, kernel_ulong_t); +extern int print_itimerspec32(struct tcb *, kernel_ulong_t); +# endif /* HAVE_ARCH_TIME32_SYSCALLS */ + # ifdef ALPHA typedef struct { int tv_sec, tv_usec; diff --git a/print_timespec.h b/print_timespec.h new file mode 100644 index 00000000..aed09434 --- /dev/null +++ b/print_timespec.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015-2016 Dmitry V. Levin + * Copyright (c) 2016-2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "xstring.h" + +#ifndef UTIME_NOW +# define UTIME_NOW ((1l << 30) - 1l) +#endif +#ifndef UTIME_OMIT +# define UTIME_OMIT ((1l << 30) - 2l) +#endif + +#define TIMESPEC_TO_SEC_NSEC(t_) \ + ((long long) (t_)->tv_sec), zero_extend_signed_to_ull((t_)->tv_nsec) + +static const char timespec_fmt[] = "{tv_sec=%lld, tv_nsec=%llu}"; + +static void +print_sec_nsec(long long sec, unsigned long long nsec) +{ + tprintf(timespec_fmt, sec, nsec); +} + +static void +print_timespec_t(const TIMESPEC_T *t) +{ + print_sec_nsec(TIMESPEC_TO_SEC_NSEC(t)); +} + +static void +print_timespec_t_utime(const TIMESPEC_T *t) +{ + switch (t->tv_nsec) { + case UTIME_NOW: + case UTIME_OMIT: + if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) + print_timespec_t(t); + if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) + break; + + (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE + ? tprints_comment : tprints)(t->tv_nsec == UTIME_NOW + ? "UTIME_NOW" : "UTIME_OMIT"); + break; + default: + print_timespec_t(t); + tprints_comment(sprinttime_nsec(TIMESPEC_TO_SEC_NSEC(t))); + break; + } +} + +bool +PRINT_TIMESPEC_DATA_SIZE(const void *arg, const size_t size) +{ + if (size < sizeof(TIMESPEC_T)) { + tprints("?"); + return false; + } + + print_timespec_t(arg); + return true; +} + +bool +PRINT_TIMESPEC_ARRAY_DATA_SIZE(const void *arg, const unsigned int nmemb, + const size_t size) +{ + const TIMESPEC_T *ts = arg; + unsigned int i; + + if (nmemb > size / sizeof(TIMESPEC_T)) { + tprints("?"); + return false; + } + + tprints("["); + + for (i = 0; i < nmemb; i++) { + if (i) + tprints(", "); + print_timespec_t(&ts[i]); + } + + tprints("]"); + return true; +} + +int +PRINT_TIMESPEC(struct tcb *const tcp, const kernel_ulong_t addr) +{ + TIMESPEC_T t; + + if (umove_or_printaddr(tcp, addr, &t)) + return -1; + + print_timespec_t(&t); + return 0; +} + +const char * +SPRINT_TIMESPEC(struct tcb *const tcp, const kernel_ulong_t addr) +{ + TIMESPEC_T t; + static char buf[sizeof(timespec_fmt) + 3 * sizeof(t)]; + + if (!addr) { + strcpy(buf, "NULL"); + } else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) || + umove(tcp, addr, &t)) { + xsprintf(buf, "%#" PRI_klx, addr); + } else { + xsprintf(buf, timespec_fmt, TIMESPEC_TO_SEC_NSEC(&t)); + } + + return buf; +} + +int +PRINT_TIMESPEC_UTIME_PAIR(struct tcb *const tcp, const kernel_ulong_t addr) +{ + TIMESPEC_T t[2]; + + if (umove_or_printaddr(tcp, addr, &t)) + return -1; + + tprints("["); + print_timespec_t_utime(&t[0]); + tprints(", "); + print_timespec_t_utime(&t[1]); + tprints("]"); + return 0; +} + +int +PRINT_ITIMERSPEC(struct tcb *const tcp, const kernel_ulong_t addr) +{ + TIMESPEC_T t[2]; + + if (umove_or_printaddr(tcp, addr, &t)) + return -1; + + tprints("{it_interval="); + print_timespec_t(&t[0]); + tprints(", it_value="); + print_timespec_t(&t[1]); + tprints("}"); + return 0; +} diff --git a/print_timespec32.c b/print_timespec32.c new file mode 100644 index 00000000..f6a16bc9 --- /dev/null +++ b/print_timespec32.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 Dmitry V. Levin + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#if HAVE_ARCH_TIME32_SYSCALLS + +# define TIMESPEC_T kernel_timespec32_t +# define PRINT_TIMESPEC_DATA_SIZE print_timespec32_data_size +# define PRINT_TIMESPEC_ARRAY_DATA_SIZE print_timespec32_array_data_size +# define PRINT_TIMESPEC print_timespec32 +# define SPRINT_TIMESPEC sprint_timespec32 +# define PRINT_TIMESPEC_UTIME_PAIR print_timespec32_utime_pair +# define PRINT_ITIMERSPEC print_itimerspec32 + +# include "kernel_timespec.h" +# include "print_timespec.h" + +#endif /* HAVE_ARCH_TIME32_SYSCALLS */ -- 2.40.0