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

[Xen-devel] [PATCH v1 5/5] xsplice: Use ld-embedded build-ids



From: Martin Pohlack <mpohlack@xxxxxxxxx>

The mechanism to get this is via the XSPLICE_OP and
we add a new subsequent hypercall to retrieve the
binary build-id. The hypercall allows an arbirarty
size (the buffer is provided to the hypervisor) - however
by default the toolstack will allocate it up to 128
bytes.

We also add two places for the build-id to be printed:
 - xsplice keyhandler. We cannot use 'hh' in the hypervisor
   snprintf handler (as it is not implemented) so instead
   we use an simpler way to print it.
 - In the 'xen-xsplice' tool add an extra parameter - build-id
   to print this as an human readable value.

Note that one can also retrieve the value by 'readelf -h xen-syms'.

Signed-off-by: Martin Pohlack <mpohlack@xxxxxxxxx>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
---
 tools/libxc/include/xenctrl.h |  1 +
 tools/libxc/xc_misc.c         | 26 +++++++++++++
 tools/misc/xen-xsplice.c      | 39 ++++++++++++++++++++
 xen/arch/x86/Makefile         |  4 +-
 xen/arch/x86/xen.lds.S        |  5 +++
 xen/common/xsplice.c          | 86 +++++++++++++++++++++++++++++++++++++++++++
 xen/include/public/sysctl.h   | 18 +++++++++
 xen/include/xen/version.h     |  1 +
 8 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 2cd982d..946ddc0 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2860,6 +2860,7 @@ int xc_xsplice_apply(xc_interface *xch, char *id);
 int xc_xsplice_revert(xc_interface *xch, char *id);
 int xc_xsplice_unload(xc_interface *xch, char *id);
 int xc_xsplice_check(xc_interface *xch, char *id);
+int xc_xsplice_build_id(xc_interface *xch, char *build_id, unsigned int max);
 
 #endif /* XENCTRL_H */
 
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index e59f0a1..f67ff16 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -992,6 +992,32 @@ int xc_xsplice_check(xc_interface *xch, char *id)
     return _xc_xsplice_action(xch, id, XSPLICE_ACTION_CHECK);
 }
 
+int xc_xsplice_build_id(xc_interface *xch, char *build_id, unsigned int max)
+{
+    int rc;
+    DECLARE_SYSCTL;
+    DECLARE_HYPERCALL_BOUNCE(build_id, max, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+
+    if ( !build_id || !max )
+        return -1;
+
+    if ( xc_hypercall_bounce_pre(xch, build_id) )
+        return -1;
+
+    sysctl.cmd = XEN_SYSCTL_xsplice_op;
+    sysctl.u.xsplice.cmd = XEN_SYSCTL_XSPLICE_INFO;
+
+    sysctl.u.xsplice.u.info.cmd = XEN_SYSCTL_XSPLICE_INFO_BUILD_ID;
+    sysctl.u.xsplice.u.info.size = max;
+
+    set_xen_guest_handle(sysctl.u.xsplice.u.info.u.info, build_id);
+
+    rc = do_sysctl(xch, &sysctl);
+
+    xc_hypercall_bounce_post(xch, build_id);
+
+    return rc;
+}
 /*
  * Local variables:
  * mode: C
diff --git a/tools/misc/xen-xsplice.c b/tools/misc/xen-xsplice.c
index d8bd222..609d799 100644
--- a/tools/misc/xen-xsplice.c
+++ b/tools/misc/xen-xsplice.c
@@ -17,6 +17,7 @@ void show_help(void)
             " <id> An unique name of payload. Up to %d characters.\n"
             "Commands:\n"
             "  help                 display this help\n"
+            "  build-id             display build-id of hypervisor.\n"
             "  upload <id> <file>   upload file <cpuid> with <id> name\n"
             "  list                 list payloads uploaded.\n"
             "  apply <id>           apply <id> patch.\n"
@@ -361,12 +362,50 @@ unload:
     return rc;
 }
 
+
+#define MAX_LEN 1024
+static int build_id_func(int argc, char *argv[])
+{
+    char binary_id[MAX_LEN];
+    char ascii_id[MAX_LEN];
+    int rc;
+    unsigned int i;
+
+    if ( argc )
+    {
+        show_help();
+        return -1;
+    }
+
+    memset(binary_id, 0, sizeof(binary_id));
+
+    rc = xc_xsplice_build_id(xch, binary_id, MAX_LEN);
+    if ( rc < 0 )
+    {
+        printf("Failed to get build_id: %d(%s)\n", errno, strerror(errno));
+        return -1;
+    }
+    /* Convert to printable format. */
+    if ( rc > MAX_LEN )
+        rc = MAX_LEN;
+
+    for ( i = 0; i < rc && (i + 1) * 2 < sizeof(binary_id); i++ )
+        snprintf(&ascii_id[i * 2], 3, "%02hhx", binary_id[i]);
+
+    ascii_id[i*2]='\0';
+    printf("%s", ascii_id);
+
+    return 0;
+}
+#undef MAX
+
 struct {
     const char *name;
     int (*function)(int argc, char *argv[]);
 } main_options[] = {
     { "help", help_func },
     { "list", list_func },
+    { "build-id", build_id_func },
     { "upload", upload_func },
     { "all", all_func },
 };
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 39a8059..de11910 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -108,11 +108,11 @@ $(TARGET)-syms: prelink.o xen.lds 
$(BASEDIR)/common/symbols-dummy.o
            $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0
        $(NM) -n $(@D)/.$(@F).0 | $(BASEDIR)/tools/symbols >$(@D)/.$(@F).0.S
        $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o
-       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
+       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o --build-id=sha1 \
            $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1
        $(NM) -n $(@D)/.$(@F).1 | $(BASEDIR)/tools/symbols >$(@D)/.$(@F).1.S
        $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o
-       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
+       $(LD) $(LDFLAGS) -T xen.lds -N prelink.o --build-id=sha1 \
            $(@D)/.$(@F).1.o -o $@
        rm -f $(@D)/.$(@F).[0-9]*
 
diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index 6553cff..2176782 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -67,6 +67,11 @@ SECTIONS
        *(.rodata.*)
   } :text
 
+  .note.gnu.build-id : {
+      __note_gnu_build_id_start = .;
+      *(.note.gnu.build-id)
+  } :text
+
   . = ALIGN(SMP_CACHE_BYTES);
   .data.read_mostly : {
        /* Exception table */
diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c
index d330efe..5728c4b 100644
--- a/xen/common/xsplice.c
+++ b/xen/common/xsplice.c
@@ -14,6 +14,8 @@
 #include <xen/sched.h>
 #include <xen/lib.h>
 #include <xen/xsplice.h>
+#include <xen/elf.h>
+#include <xen/types.h>
 #include <public/sysctl.h>
 
 #include <asm/event.h>
@@ -44,6 +46,36 @@ struct payload {
     struct tasklet tasklet;
 };
 
+#ifdef CONFIG_ARM
+static int build_id(char **p, unsigned int *len)
+{
+    return 0;
+}
+#else
+#define NT_GNU_BUILD_ID 3
+
+extern char * __note_gnu_build_id_start;  /* defined in linker script */
+static int build_id(char **p, unsigned int *len)
+{
+    Elf_Note *n;
+
+    n = (Elf_Note *)&__note_gnu_build_id_start;
+
+    /* Check if we really have a build-id. */
+    if ( NT_GNU_BUILD_ID != n->type )
+        return -ENODATA;
+
+    /* Sanity check, name should be "GNU" for ld-generated build-id. */
+    if ( strncmp(ELFNOTE_NAME(n), "GNU", n->namesz) != 0 )
+        return -ENODATA;
+
+    *len = n->descsz;
+    *p = ELFNOTE_DESC(n);
+
+    return 0;
+}
+#endif
+
 static const char *status2str(int64_t status)
 {
 #define STATUS(x) [XSPLICE_STATUS_##x] = #x
@@ -68,9 +100,31 @@ static const char *status2str(int64_t status)
     return names[status];
 }
 
+#define LEN 128
 void xsplice_printall(unsigned char key)
 {
     struct payload *data;
+    char *binary_id = NULL;
+    unsigned int len = 0;
+    int rc;
+
+    rc = build_id(&binary_id, &len);
+    printk("build-id: ");
+    if ( !rc )
+    {
+        unsigned int i;
+
+        if ( len > LEN )
+            len = LEN;
+
+        for ( i = 0; i < len; i++ )
+        {
+                   uint8_t c = binary_id[i];
+                   printk("%02x", c);
+        }
+           printk("\n");
+    } else if ( rc < 0 )
+        printk("rc = %d\n", rc);
 
     spin_lock(&payload_list_lock);
 
@@ -81,6 +135,7 @@ void xsplice_printall(unsigned char key)
     }
     spin_unlock(&payload_list_lock);
 }
+#undef LEN
 
 static int verify_id(xen_xsplice_id_t *id)
 {
@@ -415,6 +470,34 @@ static int xsplice_action(xen_sysctl_xsplice_action_t 
*action)
     return rc;
 }
 
+static int xsplice_info(xen_sysctl_xsplice_info_t *info)
+{
+    int rc;
+    unsigned int len = 0;
+    char *p = NULL;
+
+    if ( info->cmd != XEN_SYSCTL_XSPLICE_INFO_BUILD_ID )
+        return -EINVAL;
+
+    if ( info->size == 0 )
+        return -EINVAL;
+
+    if ( !guest_handle_okay(info->u.info, info->size) )
+        return -EFAULT;
+
+    rc = build_id(&p, &len);
+    if ( rc )
+        return rc;
+
+    if ( len > info->size )
+        return -ENOMEM;
+
+    if ( copy_to_guest(info->u.info, p, len) )
+        return -EFAULT;
+
+    return len;
+}
+
 int xsplice_control(xen_sysctl_xsplice_op_t *xsplice)
 {
     int rc;
@@ -433,6 +516,9 @@ int xsplice_control(xen_sysctl_xsplice_op_t *xsplice)
     case XEN_SYSCTL_XSPLICE_ACTION:
         rc = xsplice_action(&xsplice->u.action);
         break;
+    case XEN_SYSCTL_XSPLICE_INFO:
+        rc = xsplice_info(&xsplice->u.info);
+        break;
     default:
         rc = -ENOSYS;
         break;
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 08952de..583dce8 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -905,6 +905,23 @@ struct xen_sysctl_xsplice_action {
 typedef struct xen_sysctl_xsplice_action xen_sysctl_xsplice_action_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_xsplice_action_t);
 
+/*
+ * Retrieve information useful for patching tools.
+ */
+#define XEN_SYSCTL_XSPLICE_INFO 4
+/* The build-id of the hypervisor. */
+#define XEN_SYSCTL_XSPLICE_INFO_BUILD_ID 0
+struct xen_sysctl_xsplice_info {
+    uint32_t cmd;                           /* IN: XEN_SYSCTL_XSPLICE_INFO_* */
+    uint32_t size;                          /* IN: Size of info: OUT: Amount of
+                                               bytes filed out in info. */
+    union {
+        XEN_GUEST_HANDLE_64(char) info;     /* OUT: Requested information. */
+    } u;
+};
+typedef struct xen_sysctl_xsplice_info xen_sysctl_xsplice_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_xsplice_info_t);
+
 struct xen_sysctl_xsplice_op {
     uint32_t cmd;                           /* IN: XEN_SYSCTL_XSPLICE_* */
     uint32_t _pad;                          /* IN: Always zero. */
@@ -913,6 +930,7 @@ struct xen_sysctl_xsplice_op {
         xen_sysctl_xsplice_list_t list;
         xen_sysctl_xsplice_summary_t get;
         xen_sysctl_xsplice_action_t action;
+        xen_sysctl_xsplice_info_t info;
     } u;
 };
 typedef struct xen_sysctl_xsplice_op xen_sysctl_xsplice_op_t;
diff --git a/xen/include/xen/version.h b/xen/include/xen/version.h
index 81a3c7d..02f9585 100644
--- a/xen/include/xen/version.h
+++ b/xen/include/xen/version.h
@@ -12,5 +12,6 @@ unsigned int xen_minor_version(void);
 const char *xen_extra_version(void);
 const char *xen_changeset(void);
 const char *xen_banner(void);
+const char *xen_build_id(void);
 
 #endif /* __XEN_VERSION_H__ */
-- 
2.1.0


_______________________________________________
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®.