]> granicus.if.org Git - strace/blobdiff - util.c
nlattr: add UID/GID netlink attribute decoders
[strace] / util.c
diff --git a/util.c b/util.c
index 822e1ac540e1393dc76d3800fd4d1388db8739ad..035f57bfa8d766a11a1479712051b9d3d0435d59 100644 (file)
--- a/util.c
+++ b/util.c
@@ -44,6 +44,7 @@
 #include <sys/uio.h>
 
 #include "largefile_wrappers.h"
+#include "xlat.h"
 #include "xstring.h"
 
 int
@@ -988,29 +989,43 @@ dumpstr(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
        }
 }
 
+bool
+tfetch_mem64(struct tcb *const tcp, const uint64_t addr,
+            const unsigned int len, void *const our_addr)
+{
+       return addr && verbose(tcp) &&
+              (entering(tcp) || !syserror(tcp)) &&
+              !umoven(tcp, addr, len, our_addr);
+}
+
+bool
+tfetch_mem64_ignore_syserror(struct tcb *const tcp, const uint64_t addr,
+                            const unsigned int len, void *const our_addr)
+{
+       return addr && verbose(tcp) &&
+              !umoven(tcp, addr, len, our_addr);
+}
+
 int
 umoven_or_printaddr64(struct tcb *const tcp, const uint64_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) {
-               printaddr64(addr);
-               return -1;
-       }
-       return 0;
+       if (tfetch_mem64(tcp, addr, len, our_addr))
+               return 0;
+       printaddr64(addr);
+       return -1;
 }
 
 int
 umoven_or_printaddr64_ignore_syserror(struct tcb *const tcp,
-                                   const uint64_t addr,
-                                   const unsigned int len,
-                                   void *const our_addr)
+                                     const uint64_t addr,
+                                     const unsigned int len,
+                                     void *const our_addr)
 {
-       if (!addr || !verbose(tcp) || umoven(tcp, addr, len, our_addr) < 0) {
-               printaddr64(addr);
-               return -1;
-       }
-       return 0;
+       if (tfetch_mem64_ignore_syserror(tcp, addr, len, our_addr))
+               return 0;
+       printaddr64(addr);
+       return -1;
 }
 
 bool
@@ -1046,8 +1061,8 @@ print_uint64_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size,
  *
  * Array elements are being fetched to the address specified by elem_buf.
  *
- * The fetcher callback function specified by umoven_func should follow
- * the same semantics as umoven_or_printaddr function.
+ * The fetcher callback function specified by tfetch_mem_func should follow
+ * the same semantics as tfetch_mem function.
  *
  * The printer callback function specified by print_func is expected
  * to print something; if it returns false, no more iterations will be made.
@@ -1059,9 +1074,7 @@ print_uint64_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size,
  * - "NULL", if start_addr is NULL;
  * - "[]", if nmemb is 0;
  * - start_addr, if nmemb * elem_size overflows or wraps around;
- * - nothing, if the first element cannot be fetched
- *   (if umoven_func returns non-zero), but it is assumed that
- *   umoven_func has printed the address it failed to fetch data from;
+ * - start_addr, if the first tfetch_mem_func invocation returned false;
  * - elements of the array, delimited by ", ", with the array itself
  *   enclosed with [] brackets.
  *
@@ -1070,25 +1083,22 @@ print_uint64_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size,
  * - "..." is printed instead of max_strlen+1 element
  *   and no more iterations will be made.
  *
- * This function returns true only if
- * - umoven_func has been called at least once AND
- * - umoven_func has not returned false.
+ * This function returns true only if tfetch_mem_func has returned true
+ * at least once.
  */
 bool
-print_array(struct tcb *const tcp,
-           const kernel_ulong_t start_addr,
-           const size_t nmemb,
-           void *const elem_buf,
-           const size_t elem_size,
-           int (*const umoven_func)(struct tcb *,
-                                    kernel_ulong_t,
-                                    unsigned int,
-                                    void *),
-           bool (*const print_func)(struct tcb *,
-                                    void *elem_buf,
-                                    size_t elem_size,
-                                    void *opaque_data),
-           void *const opaque_data)
+print_array_ex(struct tcb *const tcp,
+              const kernel_ulong_t start_addr,
+              const size_t nmemb,
+              void *const elem_buf,
+              const size_t elem_size,
+              tfetch_mem_fn tfetch_mem_func,
+              print_fn print_func,
+              void *const opaque_data,
+              unsigned int flags,
+              const struct xlat *index_xlat,
+              size_t index_xlat_size,
+              const char *index_dflt)
 {
        if (!start_addr) {
                tprints("NULL");
@@ -1112,13 +1122,22 @@ print_array(struct tcb *const tcp,
                (abbrev(tcp) && max_strlen < nmemb) ?
                        start_addr + elem_size * max_strlen : end_addr;
        kernel_ulong_t cur;
+       kernel_ulong_t idx = 0;
+       enum xlat_style xlat_style = flags & XLAT_STYLE_MASK;
 
-       for (cur = start_addr; cur < end_addr; cur += elem_size) {
+       for (cur = start_addr; cur < end_addr; cur += elem_size, idx++) {
                if (cur != start_addr)
                        tprints(", ");
 
-               if (umoven_func(tcp, cur, elem_size, elem_buf))
+               if (!tfetch_mem_func(tcp, cur, elem_size, elem_buf)) {
+                       if (cur == start_addr)
+                               printaddr(cur);
+                       else {
+                               tprints("...");
+                               printaddr_comment(cur);
+                       }
                        break;
+               }
 
                if (cur == start_addr)
                        tprints("[");
@@ -1129,6 +1148,25 @@ print_array(struct tcb *const tcp,
                        break;
                }
 
+               if (flags & PAF_PRINT_INDICES) {
+                       tprints("[");
+
+                       if (!index_xlat) {
+                               print_xlat_ex(idx, NULL, xlat_style);
+                       } else if (flags & PAF_INDEX_XLAT_VALUE_INDEXED) {
+                               printxval_indexn_ex(index_xlat,
+                                                   index_xlat_size, idx,
+                                                   index_dflt, xlat_style);
+                       } else {
+                               printxvals_ex(idx, index_dflt, xlat_style,
+                                             (flags & PAF_INDEX_XLAT_SORTED)
+                                               && idx ? NULL : index_xlat,
+                                             NULL);
+                       }
+
+                       tprints("] = ");
+               }
+
                if (!print_func(tcp, elem_buf, elem_size, opaque_data)) {
                        cur = end_addr;
                        break;