]> granicus.if.org Git - strace/blobdiff - numa.c
tests: check decoding of vcpu auxstr
[strace] / numa.c
diff --git a/numa.c b/numa.c
index 3beb0788686b4cb34f3ba23c1df0ff0c28d4f8ae..c4500e84fd23f27341e8b7c6e1903b6baee907da 100644 (file)
--- a/numa.c
+++ b/numa.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2003-2007 Ulrich Drepper <drepper@redhat.com>
  * Copyright (c) 2005-2016 Dmitry V. Levin <ldv@altlinux.org>
+ * Copyright (c) 2016-2018 The strace developers.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include "defs.h"
 
-static void
-get_nodes(struct tcb *tcp, unsigned long ptr, unsigned long maxnodes, int err)
+static bool
+print_node(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
 {
-       unsigned long nlongs, size, end;
-
-       nlongs = (maxnodes + 8 * sizeof(long) - 1) / (8 * sizeof(long));
-       size = nlongs * sizeof(long);
-       end = ptr + size;
-       if (nlongs == 0 || ((err || verbose(tcp)) && (size * 8 == maxnodes)
-                           && (end > ptr))) {
-               unsigned long n, cur, abbrev_end;
-               int failed = 0;
-
-               if (abbrev(tcp)) {
-                       abbrev_end = ptr + max_strlen * sizeof(long);
-                       if (abbrev_end < ptr)
-                               abbrev_end = end;
-               } else {
-                       abbrev_end = end;
-               }
-               tprints(", {");
-               for (cur = ptr; cur < end; cur += sizeof(long)) {
-                       if (cur > ptr)
-                               tprints(", ");
-                       if (cur >= abbrev_end) {
-                               tprints("...");
-                               break;
-                       }
-                       if (umoven(tcp, cur, sizeof(n), &n) < 0) {
-                               tprints("?");
-                               failed = 1;
-                               break;
-                       }
-                       tprintf("%#0*lx", (int) sizeof(long) * 2 + 2, n);
-               }
-               tprints("}");
-               if (failed) {
-                       tprints(" ");
-                       printaddr(ptr);
-               }
+       if (elem_size < sizeof(kernel_ulong_t)) {
+               tprintf("%#0*x", (int) elem_size * 2 + 2,
+                       *(unsigned int *) elem_buf);
        } else {
-               tprints(" ");
-               printaddr(ptr);
+               tprintf("%#0*" PRI_klx, (int) elem_size * 2 + 2,
+                       *(kernel_ulong_t *) elem_buf);
        }
-       tprintf(", %lu", maxnodes);
+
+       return true;
+}
+
+static void
+print_nodemask(struct tcb *const tcp, const kernel_ulong_t addr,
+              const kernel_ulong_t maxnodes)
+{
+       const unsigned int bits_per_long = 8 * current_wordsize;
+       const kernel_ulong_t nmemb =
+               (maxnodes + bits_per_long - 2) / bits_per_long;
+
+       if (nmemb < maxnodes / bits_per_long ||
+           (maxnodes && !nmemb)) {
+               printaddr(addr);
+               return;
+       }
+
+       kernel_ulong_t buf;
+       print_array(tcp, addr, nmemb, &buf, current_wordsize,
+                   tfetch_mem, print_node, 0);
 }
 
 SYS_FUNC(migrate_pages)
 {
-       tprintf("%ld, ", (long) (pid_t) tcp->u_arg[0]);
-       get_nodes(tcp, tcp->u_arg[2], tcp->u_arg[1], 0);
+       tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], tcp->u_arg[1]);
+       print_nodemask(tcp, tcp->u_arg[2], tcp->u_arg[1]);
        tprints(", ");
-       get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[1], 0);
+       print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[1]);
 
        return RVAL_DECODED;
 }
@@ -91,10 +78,11 @@ SYS_FUNC(migrate_pages)
 SYS_FUNC(mbind)
 {
        printaddr(tcp->u_arg[0]);
-       tprintf(", %lu, ", tcp->u_arg[1]);
-       printxval(policies, tcp->u_arg[2], "MPOL_???");
-       get_nodes(tcp, tcp->u_arg[3], tcp->u_arg[4], 0);
+       tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
+       printxval64(policies, tcp->u_arg[2], "MPOL_???");
        tprints(", ");
+       print_nodemask(tcp, tcp->u_arg[3], tcp->u_arg[4]);
+       tprintf(", %" PRI_klu ", ", tcp->u_arg[4]);
        printflags(mbindflags, tcp->u_arg[5], "MPOL_???");
 
        return RVAL_DECODED;
@@ -103,7 +91,9 @@ SYS_FUNC(mbind)
 SYS_FUNC(set_mempolicy)
 {
        printxval(policies, tcp->u_arg[0], "MPOL_???");
-       get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], 0);
+       tprints(", ");
+       print_nodemask(tcp, tcp->u_arg[1], tcp->u_arg[2]);
+       tprintf(", %" PRI_klu, tcp->u_arg[2]);
 
        return RVAL_DECODED;
 }
@@ -114,83 +104,77 @@ SYS_FUNC(get_mempolicy)
 {
        if (exiting(tcp)) {
                int pol;
-               if (!umove_or_printaddr(tcp, tcp->u_arg[0], &pol))
+               if (!umove_or_printaddr(tcp, tcp->u_arg[0], &pol)) {
+                       tprints("[");
                        printxval(policies, pol, "MPOL_???");
-               get_nodes(tcp, tcp->u_arg[1], tcp->u_arg[2], syserror(tcp));
+                       tprints("]");
+               }
                tprints(", ");
+               print_nodemask(tcp, tcp->u_arg[1], tcp->u_arg[2]);
+               tprintf(", %" PRI_klu ", ", tcp->u_arg[2]);
                printaddr(tcp->u_arg[3]);
                tprints(", ");
-               printflags(mempolicyflags, tcp->u_arg[4], "MPOL_???");
+               printflags64(mempolicyflags, tcp->u_arg[4], "MPOL_???");
        }
        return 0;
 }
 
 #include "xlat/move_pages_flags.h"
 
+static bool
+print_addr(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
+{
+       kernel_ulong_t addr;
+
+       if (elem_size < sizeof(addr)) {
+               addr = *(unsigned int *) elem_buf;
+       } else {
+               addr = *(kernel_ulong_t *) elem_buf;
+       }
+
+       printaddr(addr);
+
+       return true;
+}
+
+static bool
+print_status(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
+{
+       const int status = *(int *) elem_buf;
+
+       if (status < 0 && (unsigned) -status < nerrnos)
+               tprintf("-%s", errnoent[-status]);
+       else
+               tprintf("%d", status);
+
+       return true;
+}
+
+static bool
+print_int(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
+{
+       tprintf("%d", *(int *) elem_buf);
+
+       return true;
+}
+
 SYS_FUNC(move_pages)
 {
+       const kernel_ulong_t npages = tcp->u_arg[1];
+       kernel_ulong_t buf;
+
        if (entering(tcp)) {
-               unsigned long npages = tcp->u_arg[1];
-               tprintf("%ld, %lu, ", tcp->u_arg[0], npages);
-               if (tcp->u_arg[2] == 0)
-                       tprints("NULL, ");
-               else {
-                       unsigned int i;
-                       long puser = tcp->u_arg[2];
-                       tprints("{");
-                       for (i = 0; i < npages; ++i) {
-                               void *p;
-                               if (i > 0)
-                                       tprints(", ");
-                               if (umove(tcp, puser, &p) < 0) {
-                                       tprints("???");
-                                       break;
-                               }
-                               tprintf("%p", p);
-                               puser += sizeof(void *);
-                       }
-                       tprints("}, ");
-               }
-               if (tcp->u_arg[3] == 0)
-                       tprints("NULL, ");
-               else {
-                       unsigned int i;
-                       long nodeuser = tcp->u_arg[3];
-                       tprints("{");
-                       for (i = 0; i < npages; ++i) {
-                               int node;
-                               if (i > 0)
-                                       tprints(", ");
-                               if (umove(tcp, nodeuser, &node) < 0) {
-                                       tprints("???");
-                                       break;
-                               }
-                               tprintf("%#x", node);
-                               nodeuser += sizeof(int);
-                       }
-                       tprints("}, ");
-               }
+               tprintf("%d, %" PRI_klu ", ", (int) tcp->u_arg[0], npages);
+               print_array(tcp, tcp->u_arg[2], npages, &buf, current_wordsize,
+                           tfetch_mem, print_addr, 0);
+               tprints(", ");
+               print_array(tcp, tcp->u_arg[3], npages, &buf, sizeof(int),
+                           tfetch_mem, print_int, 0);
+               tprints(", ");
        } else {
-               unsigned long npages = tcp->u_arg[1];
-               if (tcp->u_arg[4] == 0)
-                       tprints("NULL, ");
-               else {
-                       unsigned int i;
-                       long statususer = tcp->u_arg[4];
-                       tprints("{");
-                       for (i = 0; i < npages; ++i) {
-                               int status;
-                               if (i > 0)
-                                       tprints(", ");
-                               if (umove(tcp, statususer, &status) < 0) {
-                                       tprints("???");
-                                       break;
-                               }
-                               tprintf("%#x", status);
-                               statususer += sizeof(int);
-                       }
-                       tprints("}, ");
-               }
+               print_array(tcp, tcp->u_arg[4], npages, &buf, sizeof(int),
+                           tfetch_mem, print_status, 0);
+               tprints(", ");
                printflags(move_pages_flags, tcp->u_arg[5], "MPOL_???");
        }
        return 0;