Fixes include:
 - Error handling
 - Cleanup
 - Standard init/uninit

Signed-off-by: Sasha Levin <levinsasha...@gmail.com>
---
 tools/kvm/builtin-run.c        |   31 ++++++++++++++-------
 tools/kvm/include/kvm/symbol.h |    7 +++-
 tools/kvm/symbol.c             |   59 +++++++++++++++++++++++++++++++---------
 tools/kvm/x86/kvm-cpu.c        |   10 +++++--
 4 files changed, 79 insertions(+), 28 deletions(-)

diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
index 0234879..3d046d7 100644
--- a/tools/kvm/builtin-run.c
+++ b/tools/kvm/builtin-run.c
@@ -851,7 +851,7 @@ static int kvm_cmd_run_init(int argc, const char **argv)
        struct framebuffer *fb = NULL;
        unsigned int nr_online_cpus;
        int max_cpus, recommended_cpus;
-       int i;
+       int i, r;
 
        signal(SIGALRM, handle_sigalrm);
        kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug);
@@ -946,8 +946,6 @@ static int kvm_cmd_run_init(int argc, const char **argv)
        if (!script)
                script = DEFAULT_SCRIPT;
 
-       symbol__init(vmlinux_filename);
-
        term_init();
 
        if (!guest_name) {
@@ -1047,7 +1045,12 @@ static int kvm_cmd_run_init(int argc, const char **argv)
                                real_cmdline, vidmode))
                die("unable to load kernel %s", kernel_filename);
 
-       kvm->vmlinux            = vmlinux_filename;
+       kvm->vmlinux = vmlinux_filename;
+       r = symbol__init(kvm);
+       if (r < 0) {
+               pr_error("symbol__init() failed with error %d\n", r);
+               goto fail;
+       }
 
        ioport__setup_arch();
 
@@ -1130,7 +1133,8 @@ static int kvm_cmd_run_init(int argc, const char **argv)
        thread_pool__init(nr_online_cpus);
        ioeventfd__start();
 
-       return 0;
+fail:
+       return r;
 }
 
 static int kvm_cmd_run_work(void)
@@ -1160,10 +1164,16 @@ static int kvm_cmd_run_work(void)
        return r;
 }
 
-static int kvm_cmd_run_uninit(int guest_ret)
+static void kvm_cmd_run_uninit(int guest_ret)
 {
+       int r = 0;
+
        compat__print_all_messages();
 
+       r = symbol__uninit(kvm);
+       if (r < 0)
+               pr_warning("symbol__uninit() failed with error %d\n", r);
+
        fb__stop();
 
        virtio_blk__delete_all(kvm);
@@ -1174,17 +1184,18 @@ static int kvm_cmd_run_uninit(int guest_ret)
 
        if (guest_ret == 0)
                printf("\n  # KVM session ended normally.\n");
-
-       return 0;
 }
 
 int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 {
-       int r, ret;
+       int r, ret = -EFAULT;
 
        r = kvm_cmd_run_init(argc, argv);
+       if (r < 0)
+               goto fail;
        ret = kvm_cmd_run_work();
-       r = kvm_cmd_run_uninit(ret);
+       kvm_cmd_run_uninit(ret);
 
+fail:
        return ret;
 }
diff --git a/tools/kvm/include/kvm/symbol.h b/tools/kvm/include/kvm/symbol.h
index 5bc2221..062f411 100644
--- a/tools/kvm/include/kvm/symbol.h
+++ b/tools/kvm/include/kvm/symbol.h
@@ -6,14 +6,17 @@
 
 struct kvm;
 
+#define SYMBOL_DEFAULT_UNKNOWN "<unknown>"
+
 #ifdef CONFIG_HAS_BFD
-void symbol__init(const char *vmlinux);
+int symbol__init(struct kvm *kvm);
+int symbol__uninit(struct kvm *kvm);
 char *symbol__lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t 
size);
 #else
 static inline void symbol__init(const char *vmlinux) { }
 static inline char *symbol__lookup(struct kvm *kvm, unsigned long addr, char 
*sym, size_t size)
 {
-       char *s = strncpy(sym, "<unknown>", size);
+       char *s = strncpy(sym, SYMBOL_DEFAULT_UNKNOWN, size);
        sym[size - 1] = '\0';
        return s;
 }
diff --git a/tools/kvm/symbol.c b/tools/kvm/symbol.c
index a2b1e67..54691a4 100644
--- a/tools/kvm/symbol.c
+++ b/tools/kvm/symbol.c
@@ -2,6 +2,7 @@
 
 #include "kvm/kvm.h"
 
+#include <linux/err.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -9,19 +10,40 @@
 
 static bfd *abfd;
 
-void symbol__init(const char *vmlinux)
+int symbol__init(struct kvm *kvm)
 {
-       if (!vmlinux)
-               return;
+       int r = 0;
+
+       if (!kvm->vmlinux)
+               return -EINVAL;
 
        bfd_init();
 
-       abfd = bfd_openr(vmlinux, NULL);
+       abfd = bfd_openr(kvm->vmlinux, NULL);
+       if (abfd == NULL) {
+               bfd_error_type err = bfd_get_error();
+
+               switch(err) {
+               case bfd_error_no_memory:
+                       r = -ENOMEM;
+                       break;
+               case bfd_error_invalid_target:
+                       r = -EINVAL;
+                       break;
+               default:
+                       r = -EFAULT;
+                       break;
+               }
+       }
+
+       return r;
 }
 
 static asymbol *lookup(asymbol **symbols, int nr_symbols, const char 
*symbol_name)
 {
-       int i;
+       int i, r;
+
+       r = -ENOENT;
 
        for (i = 0; i < nr_symbols; i++) {
                asymbol *symbol = symbols[i];
@@ -30,7 +52,7 @@ static asymbol *lookup(asymbol **symbols, int nr_symbols, 
const char *symbol_nam
                        return symbol;
        }
 
-       return NULL;
+       return ERR_PTR(r);
 }
 
 char *symbol__lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t 
size)
@@ -44,9 +66,9 @@ char *symbol__lookup(struct kvm *kvm, unsigned long addr, 
char *sym, size_t size
        long symtab_size;
        asymbol *symbol;
        asymbol **syms;
-       int nr_syms;
-       char *s;
+       int nr_syms, r;
 
+       r = -ENOENT;
        if (!abfd)
                goto not_found;
 
@@ -57,13 +79,15 @@ char *symbol__lookup(struct kvm *kvm, unsigned long addr, 
char *sym, size_t size
        if (!symtab_size)
                goto not_found;
 
+       r = -ENOMEM;
        syms = malloc(symtab_size);
        if (!syms)
                goto not_found;
 
        nr_syms = bfd_canonicalize_symtab(abfd, syms);
 
-       section = bfd_get_section_by_name(abfd, ".debug_aranges");
+       r = -ENOENT;
+       section= bfd_get_section_by_name(abfd, ".debug_aranges");
        if (!section)
                goto not_found;
 
@@ -74,7 +98,7 @@ char *symbol__lookup(struct kvm *kvm, unsigned long addr, 
char *sym, size_t size
                goto not_found;
 
        symbol = lookup(syms, nr_syms, func);
-       if (!symbol)
+       if (IS_ERR(symbol))
                goto not_found;
 
        sym_start = bfd_asymbol_value(symbol);
@@ -90,9 +114,18 @@ char *symbol__lookup(struct kvm *kvm, unsigned long addr, 
char *sym, size_t size
        return sym;
 
 not_found:
-       s = strncpy(sym, "<unknown>", size);
+       return ERR_PTR(r);
+}
 
-       sym[size - 1] = '\0';
+int symbol__uninit(struct kvm *kvm)
+{
+       bfd_boolean r = TRUE;
+
+       if (abfd)
+               r = bfd_close(abfd);
+
+       if (r == TRUE)
+               return 0;
 
-       return s;
+       return -EFAULT;
 }
diff --git a/tools/kvm/x86/kvm-cpu.c b/tools/kvm/x86/kvm-cpu.c
index 051699f..4aa1b9a 100644
--- a/tools/kvm/x86/kvm-cpu.c
+++ b/tools/kvm/x86/kvm-cpu.c
@@ -6,7 +6,7 @@
 
 #include <asm/msr-index.h>
 #include <asm/apicdef.h>
-
+#include <linux/err.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <signal.h>
@@ -324,7 +324,7 @@ void kvm_cpu__show_code(struct kvm_cpu *vcpu)
        unsigned int code_bytes = 64;
        unsigned int code_prologue = 43;
        unsigned int code_len = code_bytes;
-       char sym[MAX_SYM_LEN];
+       char sym[MAX_SYM_LEN] = SYMBOL_DEFAULT_UNKNOWN, *psym;
        unsigned char c;
        unsigned int i;
        u8 *ip;
@@ -340,7 +340,11 @@ void kvm_cpu__show_code(struct kvm_cpu *vcpu)
        dprintf(debug_fd, "\n Code:\n");
        dprintf(debug_fd,   " -----\n");
 
-       symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
+       psym = symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
+       if (IS_ERR(psym))
+               dprintf(debug_fd,
+                       "Warning: symbol__lookup() failed to find symbol "
+                       "with error: %ld\n", PTR_ERR(psym));
 
        dprintf(debug_fd, " rip: [<%016lx>] %s\n\n", (unsigned long) 
vcpu->regs.rip, sym);
 
-- 
1.7.8

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to