]> granicus.if.org Git - strace/blobdiff - util.c
io: change size types from unsigned long to kernel_ureg_t
[strace] / util.c
diff --git a/util.c b/util.c
index e83f574aab28520654f5d9ed3866722b81bf6e6f..72c5251efd05ae68d190919eb8c199f62dfdc73a 100644 (file)
--- a/util.c
+++ b/util.c
@@ -53,9 +53,11 @@ string_to_uint_ex(const char *const str, char **const endptr,
        if (!*str)
                return -1;
 
+       errno = 0;
        val = strtol(str, &end, 10);
 
-       if (str == end || val < 0 || (unsigned long) val > max_val)
+       if (str == end || val < 0 || (unsigned long) val > max_val
+           || (val == LONG_MAX && errno == ERANGE))
                return -1;
 
        if (*end && (!accepted_ending || !strchr(accepted_ending, *end)))
@@ -219,10 +221,18 @@ next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits)
                pos++;
        }
 }
-/*
+
+/**
  * Print entry in struct xlat table, if there.
+ *
+ * @param val  Value to search a literal representation for.
+ * @param dflt String (abbreviated in comment syntax) which should be emitted
+ *             if no appropriate xlat value has been found.
+ * @param xlat (And the following arguments) Pointers to arrays of xlat values.
+ *             The last argument should be NULL.
+ * @return     1 if appropriate xlat value has been found, 0 otherwise.
  */
-void
+int
 printxvals(const uint64_t val, const char *dflt, const struct xlat *xlat, ...)
 {
        va_list args;
@@ -234,19 +244,34 @@ printxvals(const uint64_t val, const char *dflt, const struct xlat *xlat, ...)
                if (str) {
                        tprints(str);
                        va_end(args);
-                       return;
+                       return 1;
                }
        }
        /* No hits -- print raw # instead. */
-       tprintf("%#" PRIx64 " /* %s */", val, dflt);
+       tprintf("%#" PRIx64, val);
+       if (dflt)
+               tprintf(" /* %s */", dflt);
 
        va_end(args);
+
+       return 0;
 }
 
-/*
+/**
  * Print entry in sorted struct xlat table, if it is there.
+ *
+ * @param xlat      Pointer to an array of xlat values (not terminated with
+ *                  XLAT_END).
+ * @param xlat_size Number of xlat elements present in array (usually ARRAY_SIZE
+ *                  if array is declared in the unit's scope and not
+ *                  terminated with XLAT_END).
+ * @param val       Value to search literal representation for.
+ * @param dflt      String (abbreviated in comment syntax) which should be
+ *                  emitted if no appropriate xlat value has been found.
+ * @return          1 if appropriate xlat value has been found, 0
+ *                  otherwise.
  */
-void
+int
 printxval_searchn(const struct xlat *xlat, size_t xlat_size, uint64_t val,
        const char *dflt)
 {
@@ -254,11 +279,14 @@ printxval_searchn(const struct xlat *xlat, size_t xlat_size, uint64_t val,
 
        if (s) {
                tprints(s);
-       } else {
-               tprintf("%#" PRIx64, val);
-               if (dflt)
-                       tprintf(" /* %s */", dflt);
+               return 1;
        }
+
+       tprintf("%#" PRIx64, val);
+       if (dflt)
+               tprintf(" /* %s */", dflt);
+
+       return 0;
 }
 
 /*
@@ -269,34 +297,29 @@ int
 getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
 {
 #if SIZEOF_LONG > 4 && SIZEOF_LONG == SIZEOF_LONG_LONG
-# if SUPPORTED_PERSONALITIES > 1
-#  ifdef X86_64
-       if (current_personality != 1) {
-#  else
-       if (current_wordsize > 4) {
-#  endif
-# endif
-               *val = tcp->u_arg[arg_no];
-               arg_no++;
-# if SUPPORTED_PERSONALITIES > 1
-       } else {
+# ifndef current_klongsize
+       if (current_klongsize < SIZEOF_LONG) {
 #  if defined(AARCH64) || defined(POWERPC64)
                /* Align arg_no to the next even number. */
                arg_no = (arg_no + 1) & 0xe;
 #  endif /* AARCH64 || POWERPC64 */
-               *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
+               *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
                arg_no += 2;
+       } else
+# endif /* !current_klongsize */
+       {
+               *val = tcp->u_arg[arg_no];
+               arg_no++;
        }
-# endif /* SUPPORTED_PERSONALITIES > 1 */
 #elif SIZEOF_LONG > 4
 #  error Unsupported configuration: SIZEOF_LONG > 4 && SIZEOF_LONG_LONG > SIZEOF_LONG
 #elif HAVE_STRUCT_TCB_EXT_ARG
-# if SUPPORTED_PERSONALITIES > 1
-       if (current_personality == 1) {
-               *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
+# ifndef current_klongsize
+       if (current_klongsize < SIZEOF_LONG_LONG) {
+               *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
                arg_no += 2;
        } else
-# endif
+# endif /* !current_klongsize */
        {
                *val = tcp->ext_arg[arg_no];
                arg_no++;
@@ -319,7 +342,7 @@ getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
        if (arg_no == 3)
                arg_no++;
 # endif /* __ARM_EABI__ || LINUX_MIPSO32 || POWERPC || XTENSA || SH */
-       *val = LONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
+       *val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
        arg_no += 2;
 #endif
 
@@ -439,17 +462,18 @@ printflags64(const struct xlat *xlat, uint64_t flags, const char *dflt)
 }
 
 void
-printaddr_ull(const unsigned long long addr)
+printaddr_klu(const kernel_ulong_t addr)
 {
        if (!addr)
                tprints("NULL");
        else
-               tprintf("%#llx", addr);
+               tprintf("%#" PRI_klx, addr);
 }
 
 #define DEF_PRINTNUM(name, type) \
 bool                                                                   \
-printnum_ ## name(struct tcb *tcp, const long addr, const char *fmt)   \
+printnum_ ## name(struct tcb *const tcp, const kernel_ureg_t addr,     \
+                 const char *const fmt)                                \
 {                                                                      \
        type num;                                                       \
        if (umove_or_printaddr(tcp, addr, &num))                        \
@@ -462,7 +486,8 @@ printnum_ ## name(struct tcb *tcp, const long addr, const char *fmt)        \
 
 #define DEF_PRINTPAIR(name, type) \
 bool                                                                   \
-printpair_ ## name(struct tcb *tcp, const long addr, const char *fmt)  \
+printpair_ ## name(struct tcb *const tcp, const kernel_ureg_t addr,    \
+                  const char *const fmt)                               \
 {                                                                      \
        type pair[2];                                                   \
        if (umove_or_printaddr(tcp, addr, &pair))                       \
@@ -483,8 +508,8 @@ DEF_PRINTPAIR(int64, uint64_t)
 
 #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
 bool
-printnum_long_int(struct tcb *tcp, const long addr,
-                 const char *fmt_long, const char *fmt_int)
+printnum_long_int(struct tcb *const tcp, const kernel_ureg_t addr,
+                 const char *const fmt_long, const char *const fmt_int)
 {
        if (current_wordsize > sizeof(int)) {
                return printnum_int64(tcp, addr, fmt_long);
@@ -498,7 +523,7 @@ const char *
 sprinttime(time_t t)
 {
        struct tm *tmp;
-       static char buf[sizeof(int) * 3 * 6];
+       static char buf[sizeof(int) * 3 * 6 + sizeof("+0000")];
 
        if (t == 0) {
                strcpy(buf, "0");
@@ -506,11 +531,9 @@ sprinttime(time_t t)
        }
        tmp = localtime(&t);
        if (tmp)
-               snprintf(buf, sizeof buf, "%02d/%02d/%02d-%02d:%02d:%02d",
-                       tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
-                       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+               strftime(buf, sizeof(buf), "%FT%T%z", tmp);
        else
-               snprintf(buf, sizeof buf, "%lu", (unsigned long) t);
+               snprintf(buf, sizeof(buf), "%lu", (unsigned long) t);
 
        return buf;
 }
@@ -792,7 +815,7 @@ print_quoted_string(const char *str, unsigned int size,
  * If path length exceeds `n', append `...' to the output.
  */
 void
-printpathn(struct tcb *tcp, long addr, unsigned int n)
+printpathn(struct tcb *const tcp, const kernel_ureg_t addr, unsigned int n)
 {
        char path[PATH_MAX + 1];
        int nul_seen;
@@ -819,7 +842,7 @@ printpathn(struct tcb *tcp, long addr, unsigned int n)
 }
 
 void
-printpath(struct tcb *tcp, long addr)
+printpath(struct tcb *const tcp, const kernel_ureg_t addr)
 {
        /* Size must correspond to char path[] size in printpathn */
        printpathn(tcp, addr, PATH_MAX);
@@ -827,15 +850,15 @@ printpath(struct tcb *tcp, long addr)
 
 /*
  * Print string specified by address `addr' and length `len'.
- * If `len' == -1, set QUOTE_0_TERMINATED bit in `user_style'.
  * If `user_style' has QUOTE_0_TERMINATED bit set, treat the string
  * as a NUL-terminated string.
  * Pass `user_style' on to `string_quote'.
  * Append `...' to the output if either the string length exceeds `max_strlen',
- * or `len' != -1 and the string length exceeds `len'.
+ * or QUOTE_0_TERMINATED bit is set and the string length exceeds `len'.
  */
 void
-printstr_ex(struct tcb *tcp, long addr, long len, unsigned int user_style)
+printstr_ex(struct tcb *const tcp, const kernel_ureg_t addr,
+           const kernel_ureg_t len, const unsigned int user_style)
 {
        static char *str = NULL;
        static char *outstr;
@@ -858,22 +881,16 @@ printstr_ex(struct tcb *tcp, long addr, long len, unsigned int user_style)
                outstr = xmalloc(outstr_size);
        }
 
+       /* Fetch one byte more because string_quote may look one byte ahead. */
        size = max_strlen + 1;
-       if (len == -1) {
-               /*
-                * Treat as a NUL-terminated string: fetch one byte more
-                * because string_quote may look one byte ahead.
-                */
-               style |= QUOTE_0_TERMINATED;
+
+       if (size > len)
+               size = len;
+       if (style & QUOTE_0_TERMINATED)
                rc = umovestr(tcp, addr, size, str);
-       } else {
-               if (size > (unsigned long) len)
-                       size = (unsigned long) len;
-               if (style & QUOTE_0_TERMINATED)
-                       rc = umovestr(tcp, addr, size, str);
-               else
-                       rc = umoven(tcp, addr, size, str);
-       }
+       else
+               rc = umoven(tcp, addr, size, str);
+
        if (rc < 0) {
                printaddr(addr);
                return;
@@ -890,7 +907,7 @@ printstr_ex(struct tcb *tcp, long addr, long len, unsigned int user_style)
        ellipsis = string_quote(str, outstr, size, style)
                   && len
                   && ((style & QUOTE_0_TERMINATED)
-                      || (unsigned long) len > max_strlen);
+                      || len > max_strlen);
 
        tprints(outstr);
        if (ellipsis)
@@ -898,7 +915,8 @@ printstr_ex(struct tcb *tcp, long addr, long len, unsigned int user_style)
 }
 
 void
-dumpiov_upto(struct tcb *tcp, int len, long addr, unsigned long data_size)
+dumpiov_upto(struct tcb *const tcp, const int len, const kernel_ureg_t addr,
+            unsigned long data_size)
 {
 #if SUPPORTED_PERSONALITIES > 1
        union {
@@ -939,7 +957,7 @@ dumpiov_upto(struct tcb *tcp, int len, long addr, unsigned long data_size)
                        /* include the buffer number to make it easy to
                         * match up the trace with the source */
                        tprintf(" * %lu bytes in buffer %d\n", iov_len, i);
-                       dumpstr(tcp, (long) iov_iov_base(i), iov_len);
+                       dumpstr(tcp, (kernel_ureg_t) iov_iov_base(i), iov_len);
                }
        }
        free(iov);
@@ -950,7 +968,7 @@ dumpiov_upto(struct tcb *tcp, int len, long addr, unsigned long data_size)
 }
 
 void
-dumpstr(struct tcb *tcp, long addr, int len)
+dumpstr(struct tcb *const tcp, const kernel_ureg_t addr, const int len)
 {
        static int strsize = -1;
        static unsigned char *str;
@@ -1061,7 +1079,8 @@ static bool process_vm_readv_not_supported = 1;
 #endif /* end of hack */
 
 static ssize_t
-vm_read_mem(pid_t pid, void *laddr, long raddr, size_t len)
+vm_read_mem(const pid_t pid, void *const laddr,
+           const kernel_ureg_t raddr, const size_t len)
 {
        const struct iovec local = {
                .iov_base = laddr,
@@ -1080,7 +1099,8 @@ vm_read_mem(pid_t pid, void *laddr, long raddr, size_t len)
  * at address `addr' to our space at `our_addr'
  */
 int
-umoven(struct tcb *tcp, long addr, unsigned int len, void *our_addr)
+umoven(struct tcb *const tcp, kernel_ureg_t addr, unsigned int len,
+       void *const our_addr)
 {
        char *laddr = our_addr;
        int pid = tcp->pid;
@@ -1187,8 +1207,8 @@ umoven(struct tcb *tcp, long addr, unsigned int len, void *our_addr)
 }
 
 int
-umoven_or_printaddr(struct tcb *tcp, const long addr, const unsigned int len,
-                   void *our_addr)
+umoven_or_printaddr(struct tcb *const tcp, const kernel_ureg_t addr,
+                   const unsigned int len, void *const our_addr)
 {
        if (!addr || !verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
            umoven(tcp, addr, len, our_addr) < 0) {
@@ -1199,8 +1219,10 @@ umoven_or_printaddr(struct tcb *tcp, const long addr, const unsigned int len,
 }
 
 int
-umoven_or_printaddr_ignore_syserror(struct tcb *tcp, const long addr,
-                                   const unsigned int len, void *our_addr)
+umoven_or_printaddr_ignore_syserror(struct tcb *const tcp,
+                                   const kernel_ureg_t addr,
+                                   const unsigned int len,
+                                   void *const our_addr)
 {
        if (!addr || !verbose(tcp) || umoven(tcp, addr, len, our_addr) < 0) {
                printaddr(addr);
@@ -1222,17 +1244,10 @@ umoven_or_printaddr_ignore_syserror(struct tcb *tcp, const long addr,
  * we never write past laddr[len-1]).
  */
 int
-umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
+umovestr(struct tcb *const tcp, kernel_ureg_t addr, unsigned int len, char *laddr)
 {
-#if SIZEOF_LONG == 4
-       const unsigned long x01010101 = 0x01010101ul;
-       const unsigned long x80808080 = 0x80808080ul;
-#elif SIZEOF_LONG == 8
-       const unsigned long x01010101 = 0x0101010101010101ul;
-       const unsigned long x80808080 = 0x8080808080808080ul;
-#else
-# error SIZEOF_LONG > 8
-#endif
+       const unsigned long x01010101 = (unsigned long) 0x0101010101010101ULL;
+       const unsigned long x80808080 = (unsigned long) 0x8080808080808080ULL;
 
        int pid = tcp->pid;
        unsigned int n, m, nread;
@@ -1406,13 +1421,13 @@ umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
  * - umoven_func has not returned false.
  */
 bool
-print_array(struct tcb *tcp,
-           const unsigned long start_addr,
+print_array(struct tcb *const tcp,
+           const kernel_ureg_t start_addr,
            const size_t nmemb,
            void *const elem_buf,
            const size_t elem_size,
            int (*const umoven_func)(struct tcb *,
-                                    long,
+                                    kernel_ureg_t,
                                     unsigned int,
                                     void *),
            bool (*const print_func)(struct tcb *,
@@ -1432,17 +1447,17 @@ print_array(struct tcb *tcp,
        }
 
        const size_t size = nmemb * elem_size;
-       const unsigned long end_addr = start_addr + size;
+       const kernel_ureg_t end_addr = start_addr + size;
 
        if (end_addr <= start_addr || size / elem_size != nmemb) {
                printaddr(start_addr);
                return false;
        }
 
-       const unsigned long abbrev_end =
+       const kernel_ureg_t abbrev_end =
                (abbrev(tcp) && max_strlen < nmemb) ?
                        start_addr + elem_size * max_strlen : end_addr;
-       unsigned long cur;
+       kernel_ureg_t cur;
 
        for (cur = start_addr; cur < end_addr; cur += elem_size) {
                if (cur != start_addr)
@@ -1471,46 +1486,31 @@ print_array(struct tcb *tcp,
        return cur >= end_addr;
 }
 
-long long
-getarg_ll(struct tcb *tcp, int argn)
-{
-#if HAVE_STRUCT_TCB_EXT_ARG
-# if SUPPORTED_PERSONALITIES > 1
-       if (current_personality == 1)
-               return (long) tcp->u_arg[argn];
-       else
-# endif
-       return (long long) tcp->ext_arg[argn];
-#else
-       return (long) tcp->u_arg[argn];
-#endif
-}
-
-unsigned long long
-getarg_ull(struct tcb *tcp, int argn)
+kernel_ulong_t
+getarg_klu(struct tcb *tcp, int argn)
 {
 #if HAVE_STRUCT_TCB_EXT_ARG
-# if SUPPORTED_PERSONALITIES > 1
-       if (current_personality == 1)
-               return (unsigned long) tcp->u_arg[argn];
-       else
-# endif
-       return (unsigned long long) tcp->ext_arg[argn];
+# ifndef current_klongsize
+       if (current_klongsize < sizeof(*tcp->ext_arg)) {
+               return tcp->u_arg[argn];
+       } else
+# endif /* !current_klongsize */
+       {
+               return tcp->ext_arg[argn];
+       }
 #else
-       return (unsigned long) tcp->u_arg[argn];
+       return tcp->u_arg[argn];
 #endif
 }
 
 int
 printargs(struct tcb *tcp)
 {
-       if (entering(tcp)) {
-               int i;
-               int n = tcp->s_ent->nargs;
-               for (i = 0; i < n; i++)
-                       tprintf("%s%#llx", i ? ", " : "", getarg_ull(tcp, i));
-       }
-       return 0;
+       const int n = tcp->s_ent->nargs;
+       int i;
+       for (i = 0; i < n; ++i)
+               tprintf("%s%#" PRI_klx, i ? ", " : "", getarg_klu(tcp, i));
+       return RVAL_DECODED;
 }
 
 int