diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index 7106009d66..2f740b4789 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -15,7 +15,7 @@ LDFLAGS += $(PTHREAD_LDFLAGS)
 CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += -Wshadow
 
-XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o
+XL_OBJS = xl.o xl_cmdimpl.o xl_cmdtable.o xl_sxp.o xl_utils.o
 $(XL_OBJS): CFLAGS += $(CFLAGS_libxentoollog)
 $(XL_OBJS): CFLAGS += $(CFLAGS_XL)
 $(XL_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config.h # libxl_json.h needs it.
diff --git a/tools/xl/xl_cmdimpl.c b/tools/xl/xl_cmdimpl.c
index d9d947827d..c45ffe943f 100644
--- a/tools/xl/xl_cmdimpl.c
+++ b/tools/xl/xl_cmdimpl.c
@@ -19,7 +19,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
-#include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -48,7 +47,7 @@ libxl_ctx *ctx;
 
 xlchild children[child_max];
 
-static const char *common_domname;
+const char *common_domname;
 static int fd_lock = -1;
 
 static const char savefileheader_magic[32]=
@@ -129,22 +128,6 @@ struct domain_create {
     char **migration_domname_r; /* from malloc */
 };
 
-
-static uint32_t find_domain(const char *p) __attribute__((warn_unused_result));
-static uint32_t find_domain(const char *p)
-{
-    uint32_t domid;
-    int rc;
-
-    rc = libxl_domain_qualifier_to_domid(ctx, p, &domid);
-    if (rc) {
-        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
-        exit(EXIT_FAILURE);
-    }
-    common_domname = libxl_domid_to_name(ctx, domid);
-    return domid;
-}
-
 int child_report(xlchildnum child)
 {
     int status;
@@ -253,47 +236,6 @@ release_lock:
     return rc;
 }
 
-static void *xmalloc(size_t sz) {
-    void *r;
-    r = malloc(sz);
-    if (!r) { fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
-                      (unsigned long)sz); exit(-ERROR_FAIL); }
-    return r;
-}
-
-static void *xcalloc(size_t n, size_t sz) __attribute__((unused));
-static void *xcalloc(size_t n, size_t sz) {
-    void *r = calloc(n, sz);
-    if (!r) {
-        fprintf(stderr,"xl: Unable to calloc %zu bytes.\n", sz*n);
-        exit(-ERROR_FAIL);
-    }
-    return r;
-}
-
-static void *xrealloc(void *ptr, size_t sz) {
-    void *r;
-    if (!sz) { free(ptr); return 0; }
-      /* realloc(non-0, 0) has a useless return value;
-       * but xrealloc(anything, 0) is like free
-       */
-    r = realloc(ptr, sz);
-    if (!r) { fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
-                      (unsigned long)sz); exit(-ERROR_FAIL); }
-    return r;
-}
-
-static char *xstrdup(const char *x)
-{
-    char *r;
-    r = strdup(x);
-    if (!r) {
-        fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
-                strlen(x));
-        exit(-ERROR_FAIL);
-    }
-    return r;
-}
 
 #define ARRAY_EXTEND_INIT__CORE(array,count,initfn,more)                \
     ({                                                                  \
@@ -313,46 +255,6 @@ static char *xstrdup(const char *x)
 #define ARRAY_EXTEND_INIT_NODEVID(array,count,initfn) \
     ARRAY_EXTEND_INIT__CORE((array),(count),(initfn), /* nothing */ )
 
-static void dolog(const char *file, int line, const char *func, char *fmt, ...)
-     __attribute__((format(printf,4,5)));
-
-static void dolog(const char *file, int line, const char *func, char *fmt, ...)
-{
-    va_list ap;
-    char *s = NULL;
-    int rc;
-
-    va_start(ap, fmt);
-    rc = vasprintf(&s, fmt, ap);
-    va_end(ap);
-    if (rc >= 0)
-        /* we ignore write errors since we have no way to report them;
-         * the alternative would be to abort the whole program */
-        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
-    free(s);
-}
-
-static void xvasprintf(char **strp, const char *fmt, va_list ap)
-    __attribute__((format(printf,2,0)));
-static void xvasprintf(char **strp, const char *fmt, va_list ap)
-{
-    int r = vasprintf(strp, fmt, ap);
-    if (r == -1) {
-        perror("asprintf failed");
-        exit(EXIT_FAILURE);
-    }
-}
-
-static void xasprintf(char **strp, const char *fmt, ...)
-    __attribute__((format(printf,2,3)));
-static void xasprintf(char **strp, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    xvasprintf(strp, fmt, ap);
-    va_end(ap);
-}
-
 static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
                                             libxl_domain_config *d_config)
 {
@@ -389,19 +291,6 @@ out:
     return s;
 }
 
-static void flush_stream(FILE *fh)
-{
-    const char *fh_name =
-        fh == stdout ? "stdout" :
-        fh == stderr ? "stderr" :
-        (abort(), (const char*)0);
-
-    if (ferror(fh) || fflush(fh)) {
-        perror(fh_name);
-        exit(EXIT_FAILURE);
-    }
-}
-
 static void printf_info(enum output_format output_format,
                         int domid,
                         libxl_domain_config *d_config, FILE *fh)
@@ -437,7 +326,7 @@ out:
         fprintf(stderr,
                 "unable to format domain config as JSON (YAJL:%d)\n", s);
 
-    flush_stream(fh);
+    xflush_stream(fh);
 }
 
 static int do_daemonize(char *name, const char *pidfile)
@@ -2942,7 +2831,7 @@ static int create_domain(struct domain_create *dom_info)
             }
             fputs(json, cfg_print_fh);
             free(json);
-            flush_stream(cfg_print_fh);
+            xflush_stream(cfg_print_fh);
         }
     }
 
@@ -3294,48 +3183,6 @@ static int64_t parse_mem_size_kb(const char *mem)
     return kbytes;
 }
 
-/*
- * Callers should use SWITCH_FOREACH_OPT in preference to calling this
- * directly.
- */
-static int def_getopt(int argc, char * const argv[],
-                      const char *optstring,
-                      const struct option *longopts,
-                      const char* helpstr, int reqargs)
-{
-    int opt;
-    const struct option def_options[] = {
-        COMMON_LONG_OPTS
-    };
-
-    if (!longopts)
-        longopts = def_options;
-
-    opterr = 0;
-    while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) == '?') {
-        if (optopt == 'h') {
-            help(helpstr);
-            exit(0);
-        }
-        fprintf(stderr, "option `%c' not supported.\n", optopt);
-        exit(2);
-    }
-    if (opt == 'h') {
-        help(helpstr);
-        exit(0);
-    }
-    if (opt != -1)
-        return opt;
-
-    if (argc - optind <= reqargs - 1) {
-        fprintf(stderr, "'xl %s' requires at least %d argument%s.\n\n",
-                helpstr, reqargs, reqargs > 1 ? "s" : "");
-        help(helpstr);
-        exit(2);
-    }
-    return -1;
-}
-
 static int set_memory_max(uint32_t domid, const char *mem)
 {
     int64_t memorykb;
@@ -3364,7 +3211,7 @@ int main_memmax(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     mem = argv[optind + 1];
 
     return set_memory_max(domid, mem);
@@ -3398,7 +3245,7 @@ int main_memset(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     mem = argv[optind + 1];
 
     return set_memory_target(domid, mem);
@@ -3454,7 +3301,7 @@ int main_cd_eject(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     virtdev = argv[optind + 1];
 
     if (cd_insert(domid, virtdev, NULL))
@@ -3474,7 +3321,7 @@ int main_cd_insert(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     virtdev = argv[optind + 1];
     file = argv[optind + 2];
 
@@ -3494,7 +3341,7 @@ int main_usbctrl_attach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     libxl_device_usbctrl_init(&usbctrl);
 
@@ -3523,7 +3370,7 @@ int main_usbctrl_detach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     devid = atoi(argv[optind+1]);
 
     libxl_device_usbctrl_init(&usbctrl);
@@ -3555,7 +3402,7 @@ int main_usbdev_attach(int argc, char **argv)
 
     libxl_device_usbdev_init(&usbdev);
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
         if (parse_usbdev_config(&usbdev, *argv))
@@ -3583,7 +3430,7 @@ int main_usbdev_detach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     ctrl = atoi(argv[optind+1]);
     port = atoi(argv[optind+2]);
 
@@ -3620,7 +3467,7 @@ int main_usblist(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     if (argc > optind) {
         fprintf(stderr, "Invalid arguments.\n");
@@ -3696,7 +3543,7 @@ int main_console(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     if (!type)
         libxl_primary_console_exec(ctx, domid, -1);
     else
@@ -3721,7 +3568,7 @@ int main_vncviewer(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     if (vncviewer(domid, autopass))
         return EXIT_FAILURE;
@@ -3755,7 +3602,7 @@ int main_pcilist(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     pcilist(domid);
     return 0;
@@ -3803,7 +3650,7 @@ int main_pcidetach(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     bdf = argv[optind + 1];
 
     if (pcidetach(domid, bdf, force))
@@ -3847,7 +3694,7 @@ int main_pciattach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     bdf = argv[optind + 1];
 
     if (optind + 1 < argc)
@@ -4155,56 +4002,6 @@ out:
     }
 }
 
-static void print_bitmap(uint8_t *map, int maplen, FILE *stream)
-{
-    int i;
-    uint8_t pmap = 0, bitmask = 0;
-    int firstset = 0, state = 0;
-
-    for (i = 0; i < maplen; i++) {
-        if (i % 8 == 0) {
-            pmap = *map++;
-            bitmask = 1;
-        } else bitmask <<= 1;
-
-        switch (state) {
-        case 0:
-        case 2:
-            if ((pmap & bitmask) != 0) {
-                firstset = i;
-                state++;
-            }
-            continue;
-        case 1:
-        case 3:
-            if ((pmap & bitmask) == 0) {
-                fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
-                if (i - 1 > firstset)
-                    fprintf(stream, "-%d", i - 1);
-                state = 2;
-            }
-            continue;
-        }
-    }
-    switch (state) {
-        case 0:
-            fprintf(stream, "none");
-            break;
-        case 2:
-            break;
-        case 1:
-            if (firstset == 0) {
-                fprintf(stream, "all");
-                break;
-            }
-        case 3:
-            fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
-            if (i - 1 > firstset)
-                fprintf(stream, "-%d", i - 1);
-            break;
-    }
-}
-
 static void list_domains(bool verbose, bool context, bool claim, bool numa,
                          bool cpupool, const libxl_dominfo *info, int nb_domain)
 {
@@ -5023,7 +4820,7 @@ int main_save(int argc, char **argv)
         return EXIT_FAILURE;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     filename = argv[optind + 1];
     if ( argc - optind >= 3 )
         config_filename = argv[optind + 2];
@@ -5071,7 +4868,7 @@ int main_migrate(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     host = argv[optind + 1];
 
     bool pass_tty_arg = progress_use_cr || (isatty(2) > 0);
@@ -5112,7 +4909,7 @@ int main_dump_core(int argc, char **argv)
         /* No options */
     }
 
-    core_dump_domain(find_domain(argv[optind]), argv[optind + 1]);
+    core_dump_domain(xfind_domain(argv[optind]), argv[optind + 1]);
     return EXIT_SUCCESS;
 }
 
@@ -5124,7 +4921,7 @@ int main_pause(int argc, char **argv)
         /* No options */
     }
 
-    pause_domain(find_domain(argv[optind]));
+    pause_domain(xfind_domain(argv[optind]));
 
     return EXIT_SUCCESS;
 }
@@ -5137,7 +4934,7 @@ int main_unpause(int argc, char **argv)
         /* No options */
     }
 
-    unpause_domain(find_domain(argv[optind]));
+    unpause_domain(xfind_domain(argv[optind]));
 
     return EXIT_SUCCESS;
 }
@@ -5153,7 +4950,7 @@ int main_destroy(int argc, char **argv)
         break;
     }
 
-    destroy_domain(find_domain(argv[optind]), force);
+    destroy_domain(xfind_domain(argv[optind]), force);
     return EXIT_SUCCESS;
 }
 
@@ -5216,7 +5013,7 @@ static int main_shutdown_or_reboot(int do_reboot, int argc, char **argv)
         libxl_dominfo_list_free(dominfo, nb_domain);
     } else {
         libxl_evgen_domain_death *deathw = NULL;
-        uint32_t domid = find_domain(argv[optind]);
+        uint32_t domid = xfind_domain(argv[optind]);
 
         fn(domid, wait_for_it ? &deathw : NULL, 0, fallback_trigger);
 
@@ -5287,7 +5084,7 @@ int main_list(int argc, char **argv)
         }
         info_free = info;
     } else if (optind == argc-1) {
-        uint32_t domid = find_domain(argv[optind]);
+        uint32_t domid = xfind_domain(argv[optind]);
         rc = libxl_domain_info(ctx, &info_buf, domid);
         if (rc == ERROR_DOMAIN_NOTFOUND) {
             fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
@@ -5331,22 +5128,6 @@ int main_vm_list(int argc, char **argv)
     return EXIT_SUCCESS;
 }
 
-static void string_realloc_append(char **accumulate, const char *more)
-{
-    /* Appends more to accumulate.  Accumulate is either NULL, or
-     * points (always) to a malloc'd nul-terminated string. */
-
-    size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
-    size_t morelen = strlen(more) + 1/*nul*/;
-    if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
-        fprintf(stderr,"Additional config data far too large\n");
-        exit(-ERROR_FAIL);
-    }
-
-    *accumulate = xrealloc(*accumulate, oldlen + morelen);
-    memcpy(*accumulate + oldlen, more, morelen);
-}
-
 int main_create(int argc, char **argv)
 {
     const char *filename = NULL;
@@ -5408,8 +5189,8 @@ int main_create(int argc, char **argv)
 
     for (; optind < argc; optind++) {
         if (strchr(argv[optind], '=') != NULL) {
-            string_realloc_append(&dom_info.extra_config, argv[optind]);
-            string_realloc_append(&dom_info.extra_config, "\n");
+            xstring_realloc_append(&dom_info.extra_config, argv[optind]);
+            xstring_realloc_append(&dom_info.extra_config, "\n");
         } else if (!filename) {
             filename = argv[optind];
         } else {
@@ -5466,7 +5247,7 @@ int main_config_update(int argc, char **argv)
     fprintf(stderr, "WARNING: xl now has better capability to manage domain configuration, "
             "avoid using this command when possible\n");
 
-    domid = find_domain(argv[1]);
+    domid = xfind_domain(argv[1]);
     argc--; argv++;
 
     if (argv[1] && argv[1][0] != '-' && !strchr(argv[1], '=')) {
@@ -5485,8 +5266,8 @@ int main_config_update(int argc, char **argv)
 
     for (; optind < argc; optind++) {
         if (strchr(argv[optind], '=') != NULL) {
-            string_realloc_append(&extra_config, argv[optind]);
-            string_realloc_append(&extra_config, "\n");
+            xstring_realloc_append(&extra_config, argv[optind]);
+            xstring_realloc_append(&extra_config, "\n");
         } else if (!filename) {
             filename = argv[optind];
         } else {
@@ -5574,7 +5355,7 @@ int main_button_press(int argc, char **argv)
         /* No options */
     }
 
-    button_press(find_domain(argv[optind]), argv[optind + 1]);
+    button_press(xfind_domain(argv[optind]), argv[optind + 1]);
 
     return 0;
 }
@@ -5651,7 +5432,7 @@ static void vcpulist(int argc, char **argv)
         libxl_dominfo_list_free(dominfo, nb_domain);
     } else {
         for (; argc > 0; ++argv, --argc) {
-            uint32_t domid = find_domain(*argv);
+            uint32_t domid = xfind_domain(*argv);
             print_domain_vcpuinfo(domid, physinfo.nr_cpus);
         }
     }
@@ -5702,7 +5483,7 @@ int main_vcpupin(int argc, char **argv)
         break;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     vcpu = argv[optind+1];
     hard_str = argv[optind+2];
     soft_str = (argc > optind+3) ? argv[optind+3] : NULL;
@@ -5879,7 +5660,7 @@ int main_vcpuset(int argc, char **argv)
         break;
     }
 
-    if (vcpuset(find_domain(argv[optind]), argv[optind + 1], check_host))
+    if (vcpuset(xfind_domain(argv[optind]), argv[optind + 1], check_host))
         return EXIT_FAILURE;
 
     return EXIT_SUCCESS;
@@ -6176,7 +5957,7 @@ int main_sharing(int argc, char **argv)
         }
         info_free = info;
     } else if (optind == argc-1) {
-        uint32_t domid = find_domain(argv[optind]);
+        uint32_t domid = xfind_domain(argv[optind]);
         rc = libxl_domain_info(ctx, &info_buf, domid);
         if (rc == ERROR_DOMAIN_NOTFOUND) {
             fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
@@ -6741,7 +6522,7 @@ int main_sched_credit(int argc, char **argv)
                                 cpupool))
             return EXIT_FAILURE;
     } else {
-        uint32_t domid = find_domain(dom);
+        uint32_t domid = xfind_domain(dom);
 
         if (!opt_w && !opt_c) { /* output credit scheduler info */
             sched_credit_domain_output(-1);
@@ -6842,7 +6623,7 @@ int main_sched_credit2(int argc, char **argv)
                                 cpupool))
             return EXIT_FAILURE;
     } else {
-        uint32_t domid = find_domain(dom);
+        uint32_t domid = xfind_domain(dom);
 
         if (!opt_w) { /* output credit2 scheduler info */
             sched_credit2_domain_output(-1);
@@ -6993,7 +6774,7 @@ int main_sched_rtds(int argc, char **argv)
             goto out;
         }
     } else {
-        uint32_t domid = find_domain(dom);
+        uint32_t domid = xfind_domain(dom);
         if (!opt_v && !opt_all) { /* output default scheduling parameters */
             sched_rtds_domain_output(-1);
             rc = -sched_rtds_domain_output(domid);
@@ -7125,7 +6906,7 @@ int main_rename(int argc, char **argv)
     dom = argv[optind++];
     new_name = argv[optind];
 
-    domid = find_domain(dom);
+    domid = xfind_domain(dom);
     if (libxl_domain_rename(ctx, domid, common_domname, new_name)) {
         fprintf(stderr, "Can't rename domain '%s'.\n", dom);
         return 1;
@@ -7147,7 +6928,7 @@ int main_trigger(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     trigger_name = argv[optind++];
     if (libxl_trigger_from_string(trigger_name, &trigger)) {
@@ -7178,7 +6959,7 @@ int main_sysrq(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind++]);
+    domid = xfind_domain(argv[optind++]);
 
     sysrq = argv[optind];
 
@@ -7260,7 +7041,7 @@ int main_networkattach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     config= xlu_cfg_init(stderr, "command line");
     if (!config) {
@@ -7309,7 +7090,7 @@ int main_networklist(int argc, char **argv)
     printf("%-3s %-2s %-17s %-6s %-5s %-6s %5s/%-5s %-30s\n",
            "Idx", "BE", "Mac Addr.", "handle", "state", "evt-ch", "tx-", "rx-ring-ref", "BE-path");
     for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = find_domain(*argv);
+        uint32_t domid = xfind_domain(*argv);
         nics = libxl_device_nic_list(ctx, domid, &nb);
         if (!nics) {
             continue;
@@ -7343,7 +7124,7 @@ int main_networkdetach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     if (!strchr(argv[optind+1], ':')) {
         if (libxl_devid_to_device_nic(ctx, domid, atoi(argv[optind+1]), &nic)) {
@@ -7379,7 +7160,7 @@ int main_channellist(int argc, char **argv)
     printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
            "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
     for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
-        uint32_t domid = find_domain(*argv);
+        uint32_t domid = xfind_domain(*argv);
         channels = libxl_device_channel_list(ctx, domid, &nb);
         if (!channels)
             continue;
@@ -7491,7 +7272,7 @@ int main_blockdetach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     if (libxl_vdev_to_device_disk(ctx, domid, argv[optind+1], &disk)) {
         fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
@@ -7607,7 +7388,7 @@ int main_vtpmdetach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
 
     if ( libxl_uuid_from_string(&uuid, argv[optind+1])) {
         if (libxl_devid_to_device_vtpm(ctx, domid, atoi(argv[optind+1]), &vtpm)) {
@@ -7836,7 +7617,7 @@ int main_uptime(int argc, char **argv)
     }
 
     for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
-        domains[nb_doms] = find_domain(dom);
+        domains[nb_doms] = xfind_domain(dom);
 
     print_uptime(short_mode, domains, nb_doms);
 
@@ -7871,7 +7652,7 @@ int main_tmem_list(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     buf = libxl_tmem_list(ctx, domid, use_long);
     if (buf == NULL)
@@ -7905,7 +7686,7 @@ int main_tmem_freeze(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     if (libxl_tmem_freeze(ctx, domid) < 0)
         return EXIT_FAILURE;
@@ -7936,7 +7717,7 @@ int main_tmem_thaw(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     if (libxl_tmem_thaw(ctx, domid) < 0)
         return EXIT_FAILURE;
@@ -7982,7 +7763,7 @@ int main_tmem_set(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     if (!opt_w && !opt_c && !opt_p) {
         fprintf(stderr, "No set value specified.\n\n");
@@ -8036,7 +7817,7 @@ int main_tmem_shared_auth(int argc, char **argv)
     if (all)
         domid = INVALID_DOMID;
     else
-        domid = find_domain(dom);
+        domid = xfind_domain(dom);
 
     if (uuid == NULL || autharg == NULL) {
         fprintf(stderr, "No uuid or auth specified.\n\n");
@@ -8115,8 +7896,8 @@ int main_cpupoolcreate(int argc, char **argv)
 
     while (optind < argc) {
         if ((p = strchr(argv[optind], '='))) {
-            string_realloc_append(&extra_config, "\n");
-            string_realloc_append(&extra_config, argv[optind]);
+            xstring_realloc_append(&extra_config, "\n");
+            xstring_realloc_append(&extra_config, argv[optind]);
         } else if (!filename) {
             filename = argv[optind];
         } else {
@@ -8830,7 +8611,7 @@ int main_remus(int argc, char **argv)
         libxl_defbool_set(&r_info.colo, true);
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     host = argv[optind + 1];
 
     /* Defaults */
@@ -9179,7 +8960,7 @@ int main_psr_cmt_attach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     ret = libxl_psr_cmt_attach(ctx, domid);
 
     return ret;
@@ -9194,7 +8975,7 @@ int main_psr_cmt_detach(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     ret = libxl_psr_cmt_detach(ctx, domid);
 
     return ret;
@@ -9224,7 +9005,7 @@ int main_psr_cmt_show(int argc, char **argv)
     if (optind + 1 >= argc)
         domid = INVALID_DOMID;
     else if (optind + 1 == argc - 1)
-        domid = find_domain(argv[optind + 1]);
+        domid = xfind_domain(argv[optind + 1]);
     else {
         help("psr-cmt-show");
         return 2;
@@ -9440,7 +9221,7 @@ int main_psr_cat_cbm_set(int argc, char **argv)
         return 2;
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     cbm = strtoll(argv[optind + 1], NULL , 0);
 
     ret = libxl_psr_cat_set_cbm(ctx, domid, type, &target_map, cbm);
@@ -9461,7 +9242,7 @@ int main_psr_cat_show(int argc, char **argv)
     if (optind >= argc)
         domid = INVALID_DOMID;
     else if (optind == argc - 1)
-        domid = find_domain(argv[optind]);
+        domid = xfind_domain(argv[optind]);
     else {
         help("psr-cat-show");
         return 2;
@@ -9512,7 +9293,7 @@ int main_qemu_monitor_command(int argc, char **argv)
         /* No options */
     }
 
-    domid = find_domain(argv[optind]);
+    domid = xfind_domain(argv[optind]);
     cmd = argv[optind + 1];
 
     if (argc - optind > 2) {
diff --git a/tools/xl/xl_utils.c b/tools/xl/xl_utils.c
new file mode 100644
index 0000000000..e0b4cb2547
--- /dev/null
+++ b/tools/xl/xl_utils.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2009-2017 Citrix Ltd and other contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libxl.h>
+#include <libxl_utils.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+
+extern int logfile;
+extern const char *common_domname;
+
+void dolog(const char *file, int line, const char *func, char *fmt, ...)
+{
+    va_list ap;
+    char *s = NULL;
+    int rc;
+
+    va_start(ap, fmt);
+    rc = vasprintf(&s, fmt, ap);
+    va_end(ap);
+    if (rc >= 0)
+        /* we ignore write errors since we have no way to report them;
+         * the alternative would be to abort the whole program */
+        libxl_write_exactly(NULL, logfile, s, rc, NULL, NULL);
+    free(s);
+}
+
+void xvasprintf(char **strp, const char *fmt, va_list ap)
+{
+    int r = vasprintf(strp, fmt, ap);
+    if (r == -1) {
+        perror("asprintf failed");
+        exit(EXIT_FAILURE);
+    }
+}
+
+void xasprintf(char **strp, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    xvasprintf(strp, fmt, ap);
+    va_end(ap);
+}
+
+void *xmalloc(size_t sz)
+{
+    void *r;
+    r = malloc(sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to malloc %lu bytes.\n",
+                (unsigned long)sz);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void *xcalloc(size_t n, size_t sz)
+{
+    void *r = calloc(n, sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to calloc %zu bytes.\n", sz*n);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void *xrealloc(void *ptr, size_t sz)
+{
+    void *r;
+    if (!sz) {
+        free(ptr);
+        return 0;
+    }
+    /* realloc(non-0, 0) has a useless return value;
+     * but xrealloc(anything, 0) is like free
+     */
+    r = realloc(ptr, sz);
+    if (!r) {
+        fprintf(stderr,"xl: Unable to realloc to %lu bytes.\n",
+                (unsigned long)sz);
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+char *xstrdup(const char *x)
+{
+    char *r;
+    r = strdup(x);
+    if (!r) {
+        fprintf(stderr, "xl: Unable to strdup a string of length %zu.\n",
+                strlen(x));
+        exit(-ERROR_FAIL);
+    }
+    return r;
+}
+
+void xflush_stream(FILE *fh)
+{
+    const char *fh_name =
+        fh == stdout ? "stdout" :
+        fh == stderr ? "stderr" :
+        (abort(), (const char*)0);
+
+    if (ferror(fh) || fflush(fh)) {
+        perror(fh_name);
+        exit(EXIT_FAILURE);
+    }
+}
+
+uint32_t xfind_domain(const char *p)
+{
+    uint32_t domid;
+    int rc;
+
+    rc = libxl_domain_qualifier_to_domid(ctx, p, &domid);
+    if (rc) {
+        fprintf(stderr, "%s is an invalid domain identifier (rc=%d)\n", p, rc);
+        exit(EXIT_FAILURE);
+    }
+    common_domname = libxl_domid_to_name(ctx, domid);
+    return domid;
+}
+
+/*
+ * Callers should use SWITCH_FOREACH_OPT in preference to calling this
+ * directly.
+ */
+int xdef_getopt(int argc, char * const argv[],
+                const char *optstring,
+                const struct option *longopts,
+                const char* helpstr, int reqargs)
+{
+    int opt;
+    const struct option def_options[] = {
+        COMMON_LONG_OPTS
+    };
+
+    if (!longopts)
+        longopts = def_options;
+
+    opterr = 0;
+    while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) == '?') {
+        if (optopt == 'h') {
+            help(helpstr);
+            exit(0);
+        }
+        fprintf(stderr, "option `%c' not supported.\n", optopt);
+        exit(2);
+    }
+    if (opt == 'h') {
+        help(helpstr);
+        exit(0);
+    }
+    if (opt != -1)
+        return opt;
+
+    if (argc - optind <= reqargs - 1) {
+        fprintf(stderr, "'xl %s' requires at least %d argument%s.\n\n",
+                helpstr, reqargs, reqargs > 1 ? "s" : "");
+        help(helpstr);
+        exit(2);
+    }
+    return -1;
+}
+
+void xstring_realloc_append(char **accumulate, const char *more)
+{
+    /* Appends more to accumulate.  Accumulate is either NULL, or
+     * points (always) to a malloc'd nul-terminated string. */
+
+    size_t oldlen = *accumulate ? strlen(*accumulate) : 0;
+    size_t morelen = strlen(more) + 1/*nul*/;
+    if (oldlen > SSIZE_MAX || morelen > SSIZE_MAX - oldlen) {
+        fprintf(stderr,"Additional config data far too large\n");
+        exit(-ERROR_FAIL);
+    }
+
+    *accumulate = xrealloc(*accumulate, oldlen + morelen);
+    memcpy(*accumulate + oldlen, more, morelen);
+}
+
+void print_bitmap(uint8_t *map, int maplen, FILE *stream)
+{
+    int i;
+    uint8_t pmap = 0, bitmask = 0;
+    int firstset = 0, state = 0;
+
+    for (i = 0; i < maplen; i++) {
+        if (i % 8 == 0) {
+            pmap = *map++;
+            bitmask = 1;
+        } else bitmask <<= 1;
+
+        switch (state) {
+        case 0:
+        case 2:
+            if ((pmap & bitmask) != 0) {
+                firstset = i;
+                state++;
+            }
+            continue;
+        case 1:
+        case 3:
+            if ((pmap & bitmask) == 0) {
+                fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
+                if (i - 1 > firstset)
+                    fprintf(stream, "-%d", i - 1);
+                state = 2;
+            }
+            continue;
+        }
+    }
+    switch (state) {
+        case 0:
+            fprintf(stream, "none");
+            break;
+        case 2:
+            break;
+        case 1:
+            if (firstset == 0) {
+                fprintf(stream, "all");
+                break;
+            }
+        case 3:
+            fprintf(stream, "%s%d", state > 1 ? "," : "", firstset);
+            if (i - 1 > firstset)
+                fprintf(stream, "-%d", i - 1);
+            break;
+    }
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/xl/xl_utils.h b/tools/xl/xl_utils.h
index ebb9305b7c..2786f7c3cd 100644
--- a/tools/xl/xl_utils.h
+++ b/tools/xl/xl_utils.h
@@ -15,6 +15,8 @@
 #ifndef XL_UTILS_H
 #define XL_UTILS_H
 
+#include <getopt.h>
+
 /* For calls which return an errno on failure */
 #define CHK_ERRNOVAL( call ) ({                                         \
         int chk_errnoval = (call);                                      \
@@ -55,7 +57,7 @@
 #define LOG(_f, _a...)   dolog(__FILE__, __LINE__, __func__, _f "\n", ##_a)
 
 /*
- * Wraps def_getopt into a convenient loop+switch to process all
+ * Wraps xdef_getopt into a convenient loop+switch to process all
  * arguments. This macro is intended to be called from main_XXX().
  *
  *   SWITCH_FOREACH_OPT(int *opt, "OPTS",
@@ -110,14 +112,39 @@
  */
 #define SWITCH_FOREACH_OPT(opt, opts, longopts,                         \
                            commandname, num_required_opts)              \
-    while (((opt) = def_getopt(argc, argv, "h" opts, (longopts),        \
-                               (commandname), (num_required_opts))) != -1) \
+    while (((opt) = xdef_getopt(argc, argv, "h" opts, (longopts),       \
+                                (commandname), (num_required_opts))) != -1) \
         switch (opt)
 
 /* Must be last in list */
 #define COMMON_LONG_OPTS {"help", 0, 0, 'h'}, \
                          {0, 0, 0, 0}
 
+int xdef_getopt(int argc, char * const argv[],
+                const char *optstring,
+                const struct option *longopts,
+                const char* helpstr, int reqargs);
+
+void dolog(const char *file, int line, const char *func, char *fmt, ...)
+	__attribute__((format(printf,4,5)));
+
+void xvasprintf(char **strp, const char *fmt, va_list ap)
+	__attribute__((format(printf,2,0)));
+
+void xasprintf(char **strp, const char *fmt, ...)
+	__attribute__((format(printf,2,3)));
+
+void *xmalloc(size_t sz);
+void *xcalloc(size_t n, size_t sz);
+void *xrealloc(void *ptr, size_t sz);
+char *xstrdup(const char *x);
+void xstring_realloc_append(char **accumulate, const char *more);
+
+void xflush_stream(FILE *fh);
+uint32_t xfind_domain(const char *p) __attribute__((warn_unused_result));
+
+void print_bitmap(uint8_t *map, int maplen, FILE *stream);
+
 #endif /* XL_UTILS_H */
 
 /*
