Get rid of the type XArrayStrings in m_clientstate and use new generic
equivalents in module m_xarray instead.  A suprisingly pervasive
change.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6616 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c
index 5f713e0..b0768f7 100644
--- a/cachegrind/cg_main.c
+++ b/cachegrind/cg_main.c
@@ -42,6 +42,7 @@
 #include "pub_tool_options.h"
 #include "pub_tool_oset.h"
 #include "pub_tool_tooliface.h"
+#include "pub_tool_xarray.h"
 #include "pub_tool_clientstate.h"
 #include "pub_tool_machine.h"      // VG_(fnptr_to_fnentry)
 
@@ -1026,11 +1027,11 @@
       VG_(write)(fd, VG_(args_the_exename), 
                      VG_(strlen)( VG_(args_the_exename) ));
    }
-   for (i = 0; i < VG_(args_for_client).used; i++) {
-      if (VG_(args_for_client).strs[i]) {
+   for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+      HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
+      if (arg) {
          VG_(write)(fd, " ", 1);
-         VG_(write)(fd, VG_(args_for_client).strs[i], 
-                        VG_(strlen)(VG_(args_for_client).strs[i]));
+         VG_(write)(fd, arg, VG_(strlen)( arg ));
       }
    }
    // "events:" line
diff --git a/callgrind/command.c b/callgrind/command.c
index 1e43762..bc4ae55 100644
--- a/callgrind/command.c
+++ b/callgrind/command.c
@@ -157,9 +157,11 @@
     VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
     VG_(sprintf)(buf, " %s", VG_(args_the_exename));
     VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-    for (i = 0; i < VG_(args_for_client).used; i++) {
-	if (!VG_(args_for_client).strs[i]) continue;
-	VG_(sprintf)(buf, " %s", VG_(args_for_client).strs[i]);
+    for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+        HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
+	if (!arg) continue;
+        tl_assert( VG_(strlen)(arg) < 512-4 ); /* see [512] above */
+	VG_(sprintf)(buf, " %s", arg);
 	VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
     }
     VG_(write)(fd, "\n", 1);
@@ -230,9 +232,10 @@
     VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
     VG_(sprintf)(buf, " %s", VG_(args_the_exename));
     VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-    for (i = 0; i < VG_(args_for_client).used; i++) {
-	if (!VG_(args_for_client).strs[i]) continue;
-	VG_(sprintf)(buf, " %s", VG_(args_for_client).strs[i]);
+    for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+        HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
+	if (!arg) continue;
+	VG_(sprintf)(buf, " %s", arg);
 	VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
     }
     VG_(write)(fd, "\n", 1);
diff --git a/callgrind/dump.c b/callgrind/dump.c
index 76a5999..2904e96 100644
--- a/callgrind/dump.c
+++ b/callgrind/dump.c
@@ -1625,8 +1625,8 @@
   if (VG_(args_the_exename))
       size = VG_(sprintf)(cmdbuf, " %s", VG_(args_the_exename));
 
-  for(i = 0; i < VG_(args_for_client).used; i++) {
-      argv = VG_(args_for_client).strs[i];
+  for(i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+      argv = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
       if (!argv) continue;
       if ((size>0) && (size < BUF_LEN)) cmdbuf[size++] = ' ';
       for(j=0;argv[j]!=0;j++)
@@ -1634,7 +1634,7 @@
   }
 #else
   for(i = 0; i < VG_(client_argc); i++) {
-    argv = VG_(client_argv[i]);
+    argv = VG_(client_argv)[i];
     if (!argv) continue;
     if ((size>0) && (size < BUF_LEN)) cmdbuf[size++] = ' ';
     for(j=0;argv[j]!=0;j++)
diff --git a/callgrind/global.h b/callgrind/global.h
index 810a5d0..bb85bc6 100644
--- a/callgrind/global.h
+++ b/callgrind/global.h
@@ -19,6 +19,7 @@
 #include "pub_tool_mallocfree.h"
 #include "pub_tool_options.h"
 #include "pub_tool_tooliface.h"
+#include "pub_tool_xarray.h"
 #include "pub_tool_clientstate.h"
 #include "pub_tool_machine.h"      // VG_(fnptr_to_fnentry)
 
diff --git a/coregrind/m_clientstate.c b/coregrind/m_clientstate.c
index 966b96c..6aa3a42 100644
--- a/coregrind/m_clientstate.c
+++ b/coregrind/m_clientstate.c
@@ -32,6 +32,7 @@
 
 #include "pub_core_basics.h"
 #include "pub_core_vki.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 
 /*-----------------------------------------------------------------*/
@@ -64,10 +65,10 @@
 // (the default arena).  They are never freed.
 
 /* Args for the client. */
-XArrayStrings VG_(args_for_client) = {0,0,NULL};
+XArray* /* of HChar* */ VG_(args_for_client) = NULL;
 
 /* Args for V (augments, then those from the launcher). */
-XArrayStrings VG_(args_for_valgrind) = {0,0,NULL};
+XArray* /* of HChar* */ VG_(args_for_valgrind) = NULL;
 
 /* How many of the above not to pass on at execve time? */
 Int VG_(args_for_valgrind_noexecpass) = 0;
diff --git a/coregrind/m_commandline.c b/coregrind/m_commandline.c
index 45e7b53..aa62a1a 100644
--- a/coregrind/m_commandline.c
+++ b/coregrind/m_commandline.c
@@ -36,32 +36,16 @@
 #include "pub_core_libcprint.h"
 #include "pub_core_libcproc.h"
 #include "pub_core_mallocfree.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
-#include "pub_core_commandline.h"
+#include "pub_core_commandline.h" /* self */
 
 
 /* Add a string to an expandable array of strings. */
 
-static void add_string ( XArrayStrings* xa, HChar* str )
+static void add_string ( XArray* /* of HChar* */xa, HChar* str )
 {
-   Int     i;
-   HChar** strs2;
-   vg_assert(xa->used >= 0);
-   vg_assert(xa->size >= 0);
-   vg_assert(xa->used <= xa->size);
-   if (xa->strs == NULL) vg_assert(xa->size == 0);
-
-   if (xa->used == xa->size) {
-      xa->size = xa->size==0 ? 2 : 2*xa->size;
-      strs2 = VG_(malloc)( xa->size * sizeof(HChar*) );
-      for (i = 0; i < xa->used; i++)
-         strs2[i] = xa->strs[i];
-      if (xa->strs) 
-         VG_(free)(xa->strs);
-      xa->strs = strs2;
-   }
-   vg_assert(xa->used < xa->size);
-   xa->strs[xa->used++] = str;
+   VG_(addToXA)( xa, (void*)(&str) );
 }
 
 
@@ -112,7 +96,7 @@
       tmp = cp;
       while ( !VG_(isspace)(*cp) && *cp != 0 ) cp++;
       if ( *cp != 0 ) *cp++ = '\0';       // terminate if not the last
-      add_string( &VG_(args_for_valgrind), tmp );
+      add_string( VG_(args_for_valgrind), tmp );
    }
 }
 
@@ -163,13 +147,26 @@
           Bool augment = True;
    static Bool already_called = False;
 
-   XArrayStrings tmp_xarray = {0,0,NULL};
+   XArray* /* of HChar* */ tmp_xarray;
 
    /* This function should be called once, at startup, and then never
       again. */
    vg_assert(!already_called);
    already_called = True;
 
+   tmp_xarray = VG_(newXA)( VG_(malloc), VG_(free), sizeof(HChar*) );
+   vg_assert(tmp_xarray);
+
+   vg_assert( ! VG_(args_for_valgrind) );
+   VG_(args_for_valgrind)
+      = VG_(newXA)( VG_(malloc), VG_(free), sizeof(HChar*) );
+   vg_assert( VG_(args_for_valgrind) );
+
+   vg_assert( ! VG_(args_for_client) );
+   VG_(args_for_client)
+      = VG_(newXA)( VG_(malloc), VG_(free), sizeof(HChar*) );
+   vg_assert( VG_(args_for_client) );
+
    /* Collect up the args-for-V. */
    i = 1; /* skip the exe (stage2) name. */
    for (; i < argc; i++) {
@@ -182,7 +179,7 @@
          augment = False;
       if (argv[i][0] != '-')
 	break;
-      add_string( &tmp_xarray, argv[i] );
+      add_string( tmp_xarray, argv[i] );
    }
 
    /* Should now be looking at the exe name. */
@@ -195,13 +192,9 @@
    /* The rest are args for the client. */
    for (; i < argc; i++) {
       vg_assert(argv[i]);
-      add_string( &VG_(args_for_client), argv[i] );
+      add_string( VG_(args_for_client), argv[i] );
    }
 
-   VG_(args_for_valgrind).size = 0;
-   VG_(args_for_valgrind).used = 0;
-   VG_(args_for_valgrind).strs = NULL;
-
    /* Get extra args from ~/.valgrindrc, $VALGRIND_OPTS and
       ./.valgrindrc into VG_(args_for_valgrind). */
    if (augment) {
@@ -219,14 +212,15 @@
    }
 
    /* .. and record how many extras we got. */
-   VG_(args_for_valgrind_noexecpass) = VG_(args_for_valgrind).used;
+   VG_(args_for_valgrind_noexecpass) 
+      = VG_(sizeXA)( VG_(args_for_valgrind) );
 
    /* Finally, copy tmp_xarray onto the end. */
-   for (i = 0; i < tmp_xarray.used; i++)
-      add_string( &VG_(args_for_valgrind), tmp_xarray.strs[i] );
+   for (i = 0; i < VG_(sizeXA)( tmp_xarray ); i++)
+      add_string( VG_(args_for_valgrind), 
+                  * (HChar**)VG_(indexXA)( tmp_xarray, i ) );
 
-   if (tmp_xarray.strs)
-      VG_(free)(tmp_xarray.strs);
+   VG_(deleteXA)( tmp_xarray );
 }
 
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c
index 16e0c15..7106f1a 100644
--- a/coregrind/m_coredump/coredump-elf.c
+++ b/coregrind/m_coredump/coredump-elf.c
@@ -40,6 +40,7 @@
 #include "pub_core_libcassert.h"  // VG_(exit), vg_assert
 #include "pub_core_mallocfree.h"  // VG_(malloc), VG_(free)
 #include "pub_core_threadstate.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 #include "pub_core_options.h"
 
diff --git a/coregrind/m_debugger.c b/coregrind/m_debugger.c
index 7379252..577d03b 100644
--- a/coregrind/m_debugger.c
+++ b/coregrind/m_debugger.c
@@ -31,6 +31,7 @@
 #include "pub_core_basics.h"
 #include "pub_core_vki.h"
 #include "pub_core_threadstate.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 #include "pub_core_debugger.h"
 #include "pub_core_libcbase.h"
diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c
index 96b46f5..d670552 100644
--- a/coregrind/m_initimg/initimg-linux.c
+++ b/coregrind/m_initimg/initimg-linux.c
@@ -37,6 +37,7 @@
 #include "pub_core_libcfile.h"
 #include "pub_core_libcproc.h"
 #include "pub_core_libcprint.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 #include "pub_core_aspacemgr.h"
 #include "pub_core_mallocfree.h"
@@ -438,6 +439,7 @@
    Bool have_exename;
 
    vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
+   vg_assert( VG_(args_for_client) );
 
    /* use our own auxv as a prototype */
    orig_auxv = VG_(find_auxv)(init_sp);
@@ -464,9 +466,11 @@
    if (have_exename)
       stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
 
-   for (i = 0; i < VG_(args_for_client).used; i++) {
+   for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
       argc++;
-      stringsize += VG_(strlen)( VG_(args_for_client).strs[i] ) + 1;
+      stringsize += VG_(strlen)( * (HChar**) 
+                                   VG_(indexXA)( VG_(args_for_client), i ))
+                    + 1;
    }
 
    /* ...and the environment */
@@ -604,8 +608,11 @@
    if (have_exename)
       *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
 
-   for (i = 0; i < VG_(args_for_client).used; i++) {
-      *ptr++ = (Addr)copy_str(&strtab, VG_(args_for_client).strs[i]);
+   for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+      *ptr++ = (Addr)copy_str(
+                       &strtab, 
+                       * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
+                     );
    }
    *ptr++ = 0;
 
diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
index adf5491..2038ee4 100644
--- a/coregrind/m_libcfile.c
+++ b/coregrind/m_libcfile.c
@@ -37,6 +37,7 @@
 #include "pub_core_libcfile.h"
 #include "pub_core_libcprint.h"     // VG_(sprintf)
 #include "pub_core_libcproc.h"      // VG_(getpid), VG_(getppid)
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"   // VG_(fd_hard_limit)
 #include "pub_core_syscall.h"
 
diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c
index f607611..1dc748e 100644
--- a/coregrind/m_libcproc.c
+++ b/coregrind/m_libcproc.c
@@ -38,6 +38,7 @@
 #include "pub_core_libcsignal.h"
 #include "pub_core_mallocfree.h"
 #include "pub_core_syscall.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 
 /* ---------------------------------------------------------------------
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index b54b757..57a3ca0 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -32,6 +32,7 @@
 #include "pub_core_vki.h"
 #include "pub_core_vkiscnums.h"
 #include "pub_core_threadstate.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 #include "pub_core_aspacemgr.h"
 #include "pub_core_commandline.h"
@@ -245,10 +246,12 @@
    UInt   i;
    HChar* str;
 
-   /* parse the options we have (only the options we care about now) */
-   for (i = 0; i < VG_(args_for_valgrind).used; i++) {
+   vg_assert( VG_(args_for_valgrind) );
 
-      str = VG_(args_for_valgrind).strs[i];
+   /* parse the options we have (only the options we care about now) */
+   for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
+
+      str = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
       vg_assert(str);
 
       if (VG_STREQ(str, "--version")) {
@@ -295,9 +298,11 @@
       VG_(err_config_error)("Please use absolute paths in "
                             "./configure --prefix=... or --libdir=...");
 
-   for (i = 0; i < VG_(args_for_valgrind).used; i++) {
+   vg_assert( VG_(args_for_valgrind) );
 
-      HChar* arg   = VG_(args_for_valgrind).strs[i];
+   for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
+
+      HChar* arg   = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
       HChar* colon = arg;
 
       /* Look for a colon in the switch name */
@@ -494,7 +499,7 @@
          VG_(err_bad_option)(arg);
       }
     skip_arg:
-      if (arg != VG_(args_for_valgrind).strs[i]) {
+      if (arg != * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i )) {
          VG_(free)(arg);
       }
    }
@@ -744,6 +749,9 @@
    HChar* xpost = VG_(clo_xml) ? "</line>" : "";
    Int    i;
 
+   vg_assert( VG_(args_for_client) );
+   vg_assert( VG_(args_for_valgrind) );
+
    if (VG_(clo_xml)) {
       VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
       VG_(message)(Vg_UserMsg, "");
@@ -798,8 +806,10 @@
          VG_(getpid)(), VG_(getppid)() );
       if (VG_(args_the_exename))
          VG_(message)(Vg_UserMsg, "   %s", VG_(args_the_exename));
-      for (i = 0; i < VG_(args_for_client).used; i++) 
-         VG_(message)(Vg_UserMsg, "   %s", VG_(args_for_client).strs[i]);
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) 
+	VG_(message)(Vg_UserMsg, 
+                     "   %s", 
+                     * (HChar**) VG_(indexXA)( VG_(args_for_client), i ));
       if (VG_(clo_log_file_qualifier)) {
          HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
          VG_(message)(Vg_UserMsg, "");
@@ -835,10 +845,10 @@
       if (VG_(name_of_launcher))
          VG_(message)(Vg_UserMsg, "    <exe>%t</exe>", 
                                   VG_(name_of_launcher));
-      for (i = 0; i < VG_(args_for_valgrind).used; i++) {
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
          VG_(message)(Vg_UserMsg, 
                       "    <arg>%t</arg>", 
-                      VG_(args_for_valgrind).strs[i]);
+                      * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i ));
       }
       VG_(message)(Vg_UserMsg, "  </vargv>");
 
@@ -846,9 +856,10 @@
       if (VG_(args_the_exename))
          VG_(message)(Vg_UserMsg, "    <exe>%t</exe>", 
                                   VG_(args_the_exename));
-      for (i = 0; i < VG_(args_for_client).used; i++) {
-         VG_(message)(Vg_UserMsg, "    <arg>%t</arg>", 
-                                  VG_(args_for_client).strs[i]);
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+         VG_(message)(Vg_UserMsg,
+                      "    <arg>%t</arg>", 
+                      * (HChar**) VG_(indexXA)( VG_(args_for_client), i ));
       }
       VG_(message)(Vg_UserMsg, "  </argv>");
 
@@ -868,12 +879,16 @@
       VG_(message)(Vg_DebugMsg, "Command line");
       if (VG_(args_the_exename))
          VG_(message)(Vg_DebugMsg, "   %s", VG_(args_the_exename));
-      for (i = 0; i < VG_(args_for_client).used; i++)
-         VG_(message)(Vg_DebugMsg, "   %s", VG_(args_for_client).strs[i]);
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++)
+         VG_(message)(Vg_DebugMsg, 
+                     "   %s", 
+                     * (HChar**) VG_(indexXA)( VG_(args_for_client), i ));
 
       VG_(message)(Vg_DebugMsg, "Startup, with flags:");
-      for (i = 0; i < VG_(args_for_valgrind).used; i++) {
-         VG_(message)(Vg_DebugMsg, "   %s", VG_(args_for_valgrind).strs[i]);
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
+         VG_(message)(Vg_DebugMsg, 
+                     "   %s", 
+                     * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i ));
       }
 
       VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
@@ -1365,12 +1380,20 @@
    //--------------------------------------------------------------
    VG_(debugLog)(1, "main", "Split up command line\n");
    VG_(split_up_argv)( argc, argv );
+   vg_assert( VG_(args_for_valgrind) );
+   vg_assert( VG_(args_for_client) );
    if (0) {
-      for (i = 0; i < VG_(args_for_valgrind).used; i++)
-         VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++)
+         VG_(printf)(
+            "varg %s\n", 
+            * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i )
+         );
       VG_(printf)(" exe %s\n", VG_(args_the_exename));
-      for (i = 0; i < VG_(args_for_client).used; i++)
-         VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++)
+         VG_(printf)(
+            "carg %s\n", 
+            * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
+         );
    }
 
    //--------------------------------------------------------------
@@ -1482,9 +1505,9 @@
                      VG_(strlen)( VG_(args_the_exename) ));
       VG_(write)(fd, nul, 1);
 
-      for (i = 0; i < VG_(args_for_client).used; i++) {
-         VG_(write)(fd, VG_(args_for_client).strs[i],
-                        VG_(strlen)( VG_(args_for_client).strs[i] ));
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+         HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
+         VG_(write)(fd, arg, VG_(strlen)( arg ));
          VG_(write)(fd, nul, 1);
       }
 
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 1f929ff..057924d 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -45,6 +45,7 @@
 #include "pub_core_tooliface.h"    // VG_(needs).malloc_replacement
 #include "pub_core_machine.h"      // VG_(fnptr_to_fnentry)
 #include "pub_core_aspacemgr.h"    // VG_(am_find_nsegment)
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"  // VG_(client___libc_freeres_wrapper)
 #include "pub_core_demangle.h"     // VG_(maybe_Z_demangle)
 
diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c
index 4f265cd..6af368f 100644
--- a/coregrind/m_signals.c
+++ b/coregrind/m_signals.c
@@ -84,6 +84,7 @@
 #include "pub_core_vkiscnums.h"
 #include "pub_core_debuglog.h"
 #include "pub_core_threadstate.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 #include "pub_core_aspacemgr.h"
 #include "pub_core_debugger.h"      // For VG_(start_debugger)
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
index 2669cc3..b8c2852 100644
--- a/coregrind/m_stacktrace.c
+++ b/coregrind/m_stacktrace.c
@@ -39,6 +39,7 @@
 #include "pub_core_machine.h"
 #include "pub_core_options.h"
 #include "pub_core_stacktrace.h"
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"   // VG_(client__dl_sysinfo_int80)
 #include "pub_core_trampoline.h"
 
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index c3a10a0..3e4df0e 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -35,6 +35,7 @@
 #include "pub_core_debuginfo.h"     // VG_(di_notify_*)
 #include "pub_core_aspacemgr.h"
 #include "pub_core_transtab.h"      // VG_(discard_translations)
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"   // VG_(brk_base), VG_(brk_limit)
 #include "pub_core_debuglog.h"
 #include "pub_core_errormgr.h"
@@ -2469,14 +2470,15 @@
    if (!VG_(clo_trace_children)) {
       argv = (Char**)ARG2;
    } else {
+      vg_assert( VG_(args_for_valgrind) );
       vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
       vg_assert( VG_(args_for_valgrind_noexecpass) 
-                   <= VG_(args_for_valgrind).used );
+                   <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
       /* how many args in total will there be? */
       // launcher basename
       tot_args = 1;
       // V's args
-      tot_args += VG_(args_for_valgrind).used;
+      tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
       tot_args -= VG_(args_for_valgrind_noexecpass);
       // name of client exe
       tot_args++;
@@ -2492,10 +2494,10 @@
       // copy
       j = 0;
       argv[j++] = launcher_basename;
-      for (i = 0; i < VG_(args_for_valgrind).used; i++) {
+      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
          if (i < VG_(args_for_valgrind_noexecpass))
             continue;
-         argv[j++] = VG_(args_for_valgrind).strs[i];
+         argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
       }
       argv[j++] = (Char*)ARG1;
       if (arg2copy && arg2copy[0])
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index c34ca68..bdf12f0 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -35,6 +35,7 @@
 #include "pub_core_aspacemgr.h"
 #include "pub_core_debuginfo.h"    // VG_(di_notify_*)
 #include "pub_core_transtab.h"     // VG_(discard_translations)
+#include "pub_core_xarray.h"
 #include "pub_core_clientstate.h"
 #include "pub_core_debuglog.h"
 #include "pub_core_libcbase.h"
diff --git a/include/Makefile.am b/include/Makefile.am
index 4c854e6..f3f3ce7 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -32,4 +32,5 @@
 	pub_tool_tooliface.h 		\
 	pub_tool_vki.h			\
 	pub_tool_vkiscnums.h		\
+	pub_tool_xarray.h		\
 	valgrind.h
diff --git a/include/pub_tool_clientstate.h b/include/pub_tool_clientstate.h
index 6401282..83a830d 100644
--- a/include/pub_tool_clientstate.h
+++ b/include/pub_tool_clientstate.h
@@ -31,21 +31,14 @@
 #ifndef __PUB_TOOL_CLIENTSTATE_H
 #define __PUB_TOOL_CLIENTSTATE_H
 
+/* Note, this header requires pub_{core,tool}_xarray.h to be
+   included ahead of it. */
 
 // Command line pieces, after they have been extracted from argv in
 // m_main.main().  These are all NULL-terminated vectors.
 
-/* Expandable arrays of strings. */
-typedef
-   struct {
-      Int     size;
-      Int     used;
-      HChar** strs;
-   }
-   XArrayStrings;
-
 /* Args for the client. */
-extern XArrayStrings VG_(args_for_client);
+extern XArray* /* of HChar* */ VG_(args_for_client);
 
 /* Args for V.  This is the concatenation of the following:
    - contents of ~/.valgrindrc
@@ -59,7 +52,7 @@
    categories for themselves.  Therefore we also record the number of
    these no-pass-at-execve arguments -- that is what
    VG_(args_for_valgrind_noexecpass) is. */
-extern XArrayStrings VG_(args_for_valgrind);
+extern XArray* /* of HChar* */ VG_(args_for_valgrind);
 
 /* Number of leading args in VG_(args_for_valgrind) not to pass on at
    exec time. */
diff --git a/massif/ms_main.c b/massif/ms_main.c
index 0a3037c..dda642f 100644
--- a/massif/ms_main.c
+++ b/massif/ms_main.c
@@ -50,6 +50,7 @@
 #include "pub_tool_replacemalloc.h"
 #include "pub_tool_stacktrace.h"
 #include "pub_tool_tooliface.h"
+#include "pub_tool_xarray.h"
 #include "pub_tool_clientstate.h"
 
 #include "valgrind.h"           // For {MALLOC,FREE}LIKE_BLOCK
@@ -1296,9 +1297,10 @@
    if (VG_(args_the_exename)) {
       SPRINTF(buf, "%s", VG_(args_the_exename));
    }
-   for (i = 0; i < VG_(args_for_client).used; i++) {
-      if (VG_(args_for_client).strs[i])
-         SPRINTF(buf, " %s", VG_(args_for_client).strs[i]);
+   for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+       HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
+      if (arg)
+         SPRINTF(buf, " %s", arg);
    }
    SPRINTF(buf, /*" (%d ms/sample)\"\n"*/ "\"\n"
                 "DATE        \"\"\n"
@@ -1619,9 +1621,10 @@
    if (VG_(args_the_exename)) {
       SPRINTF(buf, " %s", VG_(args_the_exename));
    }
-   for (i = 0; i < VG_(args_for_client).used; i++) {
-      if (VG_(args_for_client).strs[i])
-         SPRINTF(buf, " %s", VG_(args_for_client).strs[i]);
+   for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
+      HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
+      if (arg)
+         SPRINTF(buf, " %s", arg);
    }
    SPRINTF(buf, "\n%s\n", maybe_p);