[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 2/2] Add xen-hyp-rw



This allows reading and writing of variables in the hypervisor.

for example (read case -- default 4 bytes):

  xen-hyp-rw /boot/System.map-xen* opt_hvm_debug_level
  opt_hvm_debug_level @ 0xffff82d080285610 is 0x0(0)

Write case:

  xen-hyp-rw /boot/System.map-xen* opt_hvm_debug_level 4 -1
  opt_hvm_debug_level @ 0xffff82d080285610 is 0x0(0)
  opt_hvm_debug_level @ 0xffff82d080285610 set to 0xffffffff(4294967295)

Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx>
CC: Don Slutz <don.slutz@xxxxxxxxx>
---
 .gitignore                          |   1 +
 tools/debugger/gdbsx/Makefile       |   7 +-
 tools/debugger/gdbsx/xen-hyp-rw.c   | 209 ++++++++++++++++++++++++++++++++++++
 tools/debugger/gdbsx/xg/xg_main.c   |  28 +++++
 tools/debugger/gdbsx/xg/xg_public.h |   2 +
 5 files changed, 246 insertions(+), 1 deletion(-)
 create mode 100644 tools/debugger/gdbsx/xen-hyp-rw.c

diff --git a/.gitignore b/.gitignore
index 3f42ded..73dce09 100644
--- a/.gitignore
+++ b/.gitignore
@@ -104,6 +104,7 @@ tools/debugger/gdb/gdb-6.2.1-linux-i386-xen/*
 tools/debugger/gdb/gdb-6.2.1/*
 tools/debugger/gdb/gdb-6.2.1.tar.bz2
 tools/debugger/gdbsx/gdbsx
+tools/debugger/gdbsx/xen-hyp-rw
 tools/debugger/xenitp/xenitp
 tools/firmware/*/biossums
 tools/firmware/*.bin
diff --git a/tools/debugger/gdbsx/Makefile b/tools/debugger/gdbsx/Makefile
index 4ed6d76..6a8c4ac 100644
--- a/tools/debugger/gdbsx/Makefile
+++ b/tools/debugger/gdbsx/Makefile
@@ -6,10 +6,11 @@ all:
        $(MAKE) -C gx
        $(MAKE) -C xg
        $(MAKE) gdbsx
+       $(MAKE) xen-hyp-rw
 
 .PHONY: clean
 clean:
-       rm -f xg_all.a gx_all.a gdbsx
+       rm -f xg_all.a gx_all.a gdbsx xen-hyp-rw
        set -e; for d in xg gx; do $(MAKE) -C $$d clean; done
 
 .PHONY: distclean
@@ -20,10 +21,14 @@ distclean: clean
 install: all
        [ -d $(DESTDIR)$(sbindir) ] || $(INSTALL_DIR) $(DESTDIR)$(sbindir)
        $(INSTALL_PROG) gdbsx $(DESTDIR)$(sbindir)/gdbsx
+       $(INSTALL_PROG) xen-hyp-rw $(DESTDIR)$(sbindir)/xen-hyp-rw
 
 gdbsx: gx/gx_all.a xg/xg_all.a 
        $(CC) -o $@ $^
 
+xen-hyp-rw: xen-hyp-rw.c gx/gx_all.a xg/xg_all.a
+       $(CC) $(CFLAGS) $(CFLAGS_xeninclude) -o $@ $^
+
 xg/xg_all.a:
        $(MAKE) -C xg
 gx/gx_all.a:
diff --git a/tools/debugger/gdbsx/xen-hyp-rw.c 
b/tools/debugger/gdbsx/xen-hyp-rw.c
new file mode 100644
index 0000000..ee10fe9
--- /dev/null
+++ b/tools/debugger/gdbsx/xen-hyp-rw.c
@@ -0,0 +1,209 @@
+/******************************************************************************
+ * tools/debugger/gdbsx/xen-hyp-rw.c
+ *
+ * read and write hypervisor memory.
+ *
+ * Copyright (C) 2014 by Verizon.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <signal.h>
+#include <ctype.h>
+
+#include <xen/xen.h>
+
+typedef unsigned char uchar;
+typedef long long unsigned int u64;
+
+#include "xg/xg_public.h"
+
+void gxprt(const char *fmt, ...);
+
+static u64 read_symbol_table(const char *symtab, const char *who)
+{
+    u64 ret = 0;
+    char type, line[256];
+    char *p;
+    FILE *f;
+    u64 address;
+
+    f = fopen(symtab, "r");
+    if ( f == NULL )
+    {
+        fprintf(stderr, "failed to open symbol table %s\n", symtab);
+        exit(-1);
+    }
+
+    while ( !feof(f) )
+    {
+        if ( fgets(line, 256, f) == NULL )
+            break;
+
+        /* need more checks for syntax here... */
+        address = strtoull(line, &p, 16);
+        if ( !isspace((uint8_t)*p++) )
+            continue;
+        type = *p++;
+        if ( !isalpha((uint8_t)type) && type != '?' )
+            continue;
+        if ( !isspace((uint8_t)*p++) )
+            continue;
+
+        /* in the future we should handle the module name
+         * being appended here, this would allow us to use
+         * /proc/kallsyms as our symbol table
+         */
+        if ( p[strlen(p) - 1] == '\n' )
+            p[strlen(p) - 1] = '\0';
+
+        switch ( type )
+        {
+        case 'A': /* global absolute */
+        case 'a': /* local absolute */
+            break;
+        case 'U': /* undefined */
+        case 'v': /* undefined weak object */
+        case 'w': /* undefined weak function */
+            continue;
+        default:
+            break;
+        }
+
+        if ( strcmp(p, who) == 0 )
+            ret = address;
+    }
+
+    fclose(f);
+
+    return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+    domid_t domid = DOMID_IDLE;
+    int exit_rc = 0;
+    u64 hyp_va;
+    u64 val = 0;
+    long len = sizeof(int);
+    char *endptr = NULL;
+    int remain;
+
+    if ( strcmp(argv[argc - 1], "-d") == 0 )
+    {
+        xgtrc_on = 1;       /* debug trace on */
+        argc--;
+    }
+
+    if ( argc < 3 )
+    {
+        printf("Usage: %s [-d] <symbol file> <symbol> [<length> [<new 
value>]]\n",
+               argv[0]);
+        gxprt("ERROR: Need symbol file and symbol\n");
+        exit(1);
+    }
+
+    hyp_va = read_symbol_table(argv[1], argv[2]);
+    if ( !hyp_va )
+    {
+        gxprt("ERROR: failed to find symbol:%s\n", argv[2]);
+        exit(1);
+    }
+
+    if ( argc > 3 )
+    {
+        errno = 0;
+        len = strtol(argv[3], &endptr, 0);
+        if ( endptr == argv[3] ||
+             *endptr )
+        {
+            gxprt("ERROR: Failed to convert '%s' to a long.\n",
+                  argv[3]);
+            exit(2);
+        }
+        if ( len < 1 )
+        {
+            gxprt("ERROR: length=%ld too small.\n", len);
+            exit(3);
+        }
+        else if ( len > sizeof(val) )
+        {
+            gxprt("ERROR: length=%ld too big.\n", len);
+            exit(4);
+        }
+    }
+
+    if ( xg_init() == -1 )
+    {
+        gxprt("ERROR: failed to initialize errno:%d\n", errno);
+        exit(1);
+    }
+    if ( (hyp_attach(domid)) == -1 )
+    {
+        gxprt("ERROR: failed to attach to domain:%d errno:%d\n",
+              domid, errno);
+        exit(1);
+    }
+    if ( (remain = xg_read_mem(hyp_va, (char *)&val, len, 0) != 0) )
+        XGERR("Failed read mem. addr:0x%llx len:%d remn:%d errno:%d\n",
+              hyp_va, len, remain, errno);
+    else
+    {
+        printf("%s @ 0x%llx is 0x%llx(%lld)\n",
+               argv[2], hyp_va, val, val);
+        if ( argc > 4 )
+        {
+            u64 new = strtoll(argv[4], &endptr, 0);
+
+            if ( endptr && (*endptr == 0) )
+            {
+                if ( (remain = xg_write_mem(hyp_va, (char *)&new, len, 0)
+                      != 0) )
+                    XGERR(
+                        "Failed write addr:0x%llx len:%d remn:%d errno:%d\n",
+                        hyp_va, len, remain, errno);
+                else
+                {
+                    if ( (remain = xg_read_mem(hyp_va, (char *)&val, len, 0)
+                          != 0) )
+                        XGERR(
+                            "Failed read addr:0x%llx len:%d remn:%d 
errno:%d\n",
+                            hyp_va, len, remain, errno);
+                    printf("%s @ 0x%llx set to 0x%llx(%lld)\n",
+                           argv[2], hyp_va, val, val);
+                }
+            }
+        }
+    }
+
+    hyp_detach();
+    return exit_rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/debugger/gdbsx/xg/xg_main.c 
b/tools/debugger/gdbsx/xg/xg_main.c
index c95e4ed..32e16a4 100644
--- a/tools/debugger/gdbsx/xg/xg_main.c
+++ b/tools/debugger/gdbsx/xg/xg_main.c
@@ -340,6 +340,7 @@ xg_detach_deinit(void)
         _unpause_domain();
         
     close(_dom0_fd);
+    munlock(&domctl, sizeof(domctl));
 }
 
 /* 
@@ -829,6 +830,33 @@ xg_write_mem(uint64_t guestva, char *frombuf, int buflen, 
uint64_t pgd3val)
 }
 
 /*
+ * Attach to xen for debugging.
+ */
+int
+hyp_attach(int domid)
+{
+    XGTRC("E:domid:%d\n", domid);
+
+    _dom_id = domctl.domain = domid;
+    domctl.interface_version = XEN_DOMCTL_INTERFACE_VERSION;
+
+    if (mlock(&domctl, sizeof(domctl))) {
+        XGERR("Unable to pin domctl in memory. errno:%d\n", errno);
+        return -1;
+    }
+
+    return 0;
+}
+
+/* Detach from xen for debugger exit */
+void
+hyp_detach(void)
+{
+    close(_dom0_fd);
+    munlock(&domctl, sizeof(domctl));
+}
+
+/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/tools/debugger/gdbsx/xg/xg_public.h 
b/tools/debugger/gdbsx/xg/xg_public.h
index 6236d08..976cf5e 100644
--- a/tools/debugger/gdbsx/xg/xg_public.h
+++ b/tools/debugger/gdbsx/xg/xg_public.h
@@ -108,3 +108,5 @@ int xg_read_mem(uint64_t, char *, int, uint64_t);
 int xg_write_mem(uint64_t, char *, int, uint64_t);
 void xgprt(const char *fn, const char *fmt, ...);
 void xgtrc(const char *fn, const char *fmt, ...);
+int hyp_attach(int);
+void hyp_detach(void);
-- 
1.8.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.