From: Pekka Enberg <penberg@kernel.org>
To: kvm@vger.kernel.org
Cc: Pekka Enberg <penberg@kernel.org>,
Asias He <asias.hejun@gmail.com>, Avi Kivity <avi@redhat.com>,
Cyrill Gorcunov <gorcunov@gmail.com>, Ingo Molnar <mingo@elte.hu>,
Prasad Joshi <prasadjoshi124@gmail.com>,
Sasha Levin <levinsasha928@gmail.com>
Subject: [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3'
Date: Wed, 11 May 2011 23:09:49 +0300 [thread overview]
Message-ID: <1305144589-21229-1-git-send-email-penberg@kernel.org> (raw)
To make debugging easier, look up symbol from guest kernel image based on RIP
when user does 'kill -3' to the hypervisor.
Example output looks as follows:
Code:
-----
rip: [<ffffffff812cb3a0>] delay_loop+30 (/home/penberg/linux/arch/x86/lib/delay.c:32)
Cc: Asias He <asias.hejun@gmail.com>
Cc: Avi Kivity <avi@redhat.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Prasad Joshi <prasadjoshi124@gmail.com>
Cc: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
---
tools/kvm/Makefile | 2 +
tools/kvm/include/kvm/kvm.h | 2 +
tools/kvm/include/kvm/symbol.h | 12 +++++
tools/kvm/kvm-cpu.c | 9 ++++
tools/kvm/kvm-run.c | 43 +++++++++++++++--
tools/kvm/symbol.c | 98 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 161 insertions(+), 5 deletions(-)
create mode 100644 tools/kvm/include/kvm/symbol.h
create mode 100644 tools/kvm/symbol.c
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index fb839fc..1aaed24 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -24,6 +24,7 @@ OBJS += main.o
OBJS += mmio.o
OBJS += pci.o
OBJS += rtc.o
+OBJS += symbol.o
OBJS += term.o
OBJS += util.o
OBJS += virtio/blk.o
@@ -50,6 +51,7 @@ OBJS += bios/bios.o
LIBS += -lrt
LIBS += -lpthread
+LIBS += -lbfd
# Additional ARCH settings for x86
ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
index 501c74c..b310d50 100644
--- a/tools/kvm/include/kvm/kvm.h
+++ b/tools/kvm/include/kvm/kvm.h
@@ -28,6 +28,8 @@ struct kvm {
u16 boot_sp;
struct interrupt_table interrupt_table;
+
+ const char *vmlinux;
};
struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size);
diff --git a/tools/kvm/include/kvm/symbol.h b/tools/kvm/include/kvm/symbol.h
new file mode 100644
index 0000000..eaa84ea
--- /dev/null
+++ b/tools/kvm/include/kvm/symbol.h
@@ -0,0 +1,12 @@
+#ifndef KVM__SYMBOL_H
+#define KVM__SYMBOL_H
+
+#include <stddef.h>
+
+struct kvm;
+
+void symbol__init(const char *vmlinux);
+
+char *symbol__lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size);
+
+#endif /* KVM__SYMBOL_H */
diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
index 8a27e02..a507fa4 100644
--- a/tools/kvm/kvm-cpu.c
+++ b/tools/kvm/kvm-cpu.c
@@ -1,5 +1,6 @@
#include "kvm/kvm-cpu.h"
+#include "kvm/symbol.h"
#include "kvm/util.h"
#include "kvm/kvm.h"
@@ -9,6 +10,7 @@
#include <sys/mman.h>
#include <signal.h>
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
#include <stdio.h>
@@ -282,11 +284,14 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
printf("\n");
}
+#define MAX_SYM_LEN 128
+
void kvm_cpu__show_code(struct kvm_cpu *vcpu)
{
unsigned int code_bytes = 64;
unsigned int code_prologue = code_bytes * 43 / 64;
unsigned int code_len = code_bytes;
+ char sym[MAX_SYM_LEN];
unsigned char c;
unsigned int i;
u8 *ip;
@@ -302,6 +307,10 @@ void kvm_cpu__show_code(struct kvm_cpu *vcpu)
printf("\n Code:\n");
printf( " -----\n");
+ symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
+
+ printf(" rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
+
for (i = 0; i < code_len; i++, ip++) {
if (!host_ptr_in_ram(vcpu->kvm, ip))
break;
diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
index 84f05cb..91a194e 100644
--- a/tools/kvm/kvm-run.c
+++ b/tools/kvm/kvm-run.c
@@ -26,6 +26,7 @@
#include <kvm/ioport.h>
#include <kvm/threadpool.h>
#include <kvm/barrier.h>
+#include <kvm/symbol.h>
/* header files for gitish interface */
#include <kvm/kvm-run.h>
@@ -52,6 +53,7 @@ static u64 ram_size;
static u8 image_count;
static const char *kernel_cmdline;
static const char *kernel_filename;
+static const char *vmlinux_filename;
static const char *initrd_filename;
static const char *image_filename[MAX_DISK_IMAGES];
static const char *console;
@@ -214,17 +216,25 @@ panic_kvm:
}
static char kernel[PATH_MAX];
-const char *host_kernels[] = {
+
+static const char *host_kernels[] = {
"/boot/vmlinuz",
"/boot/bzImage",
NULL
};
-const char *default_kernels[] = {
+
+static const char *default_kernels[] = {
"./bzImage",
"../../arch/x86/boot/bzImage",
NULL
};
+static const char *default_vmlinux[] = {
+ "../../../vmlinux",
+ "../../vmlinux",
+ NULL
+};
+
static void kernel_usage_with_options(void)
{
const char **k;
@@ -317,6 +327,23 @@ static const char *find_kernel(void)
return NULL;
}
+static const char *find_vmlinux(void)
+{
+ const char **vmlinux;
+
+ vmlinux = &default_vmlinux[0];
+ while (*vmlinux) {
+ struct stat st;
+
+ if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) {
+ vmlinux++;
+ continue;
+ }
+ return *vmlinux;
+ }
+ return NULL;
+}
+
static int root_device(char *dev, long *part)
{
struct stat st;
@@ -359,13 +386,13 @@ static char *host_image(char *cmd_line, size_t size)
int kvm_cmd_run(int argc, const char **argv, const char *prefix)
{
+ struct virtio_net_parameters net_params;
static char real_cmdline[2048];
unsigned int nr_online_cpus;
- int max_cpus;
int exit_code = 0;
- int i;
- struct virtio_net_parameters net_params;
+ int max_cpus;
char *hi;
+ int i;
signal(SIGALRM, handle_sigalrm);
signal(SIGQUIT, handle_sigquit);
@@ -399,6 +426,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
return EINVAL;
}
+ vmlinux_filename = find_vmlinux();
+
if (nrcpus < 1 || nrcpus > KVM_NR_CPUS)
die("Number of CPUs %d is out of [1;%d] range", nrcpus, KVM_NR_CPUS);
@@ -433,6 +462,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
if (!script)
script = DEFAULT_SCRIPT;
+ symbol__init(vmlinux_filename);
+
term_init();
kvm = kvm__init(kvm_dev, ram_size);
@@ -482,6 +513,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
real_cmdline))
die("unable to load kernel %s", kernel_filename);
+ kvm->vmlinux = vmlinux_filename;
+
ioport__setup_legacy();
rtc__init();
diff --git a/tools/kvm/symbol.c b/tools/kvm/symbol.c
new file mode 100644
index 0000000..56dd346
--- /dev/null
+++ b/tools/kvm/symbol.c
@@ -0,0 +1,98 @@
+#include "kvm/symbol.h"
+
+#include "kvm/kvm.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <bfd.h>
+
+static bfd *abfd;
+
+void symbol__init(const char *vmlinux)
+{
+ if (!vmlinux)
+ return;
+
+ bfd_init();
+
+ abfd = bfd_openr(vmlinux, NULL);
+}
+
+static asymbol *lookup(asymbol **symbols, int nr_symbols, const char *symbol_name)
+{
+ int i;
+
+ for (i = 0; i < nr_symbols; i++) {
+ asymbol *symbol = symbols[i];
+
+ if (!strcmp(bfd_asymbol_name(symbol), symbol_name))
+ return symbol;
+ }
+
+ return NULL;
+}
+
+char *symbol__lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size)
+{
+ const char *filename;
+ bfd_vma sym_offset;
+ bfd_vma sym_start;
+ asection *section;
+ unsigned int line;
+ const char *func;
+ long symtab_size;
+ asymbol *symbol;
+ asymbol **syms;
+ int nr_syms;
+ char *s;
+
+ if (!abfd)
+ goto not_found;
+
+ if (!bfd_check_format(abfd, bfd_object))
+ goto not_found;
+
+ symtab_size = bfd_get_symtab_upper_bound(abfd);
+ if (!symtab_size)
+ goto not_found;
+
+ 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");
+ if (!section)
+ goto not_found;
+
+ if (!bfd_find_nearest_line(abfd, section, NULL, addr, &filename, &func, &line))
+ goto not_found;
+
+ if (!func)
+ goto not_found;
+
+ symbol = lookup(syms, nr_syms, func);
+ if (!symbol)
+ goto not_found;
+
+ sym_start = bfd_asymbol_value(symbol);
+
+ sym_offset = addr - sym_start;
+
+ snprintf(sym, size, "%s+%llx (%s:%i)", func, (long long) sym_offset, filename, line);
+
+ sym[size - 1] = '\0';
+
+ free(syms);
+
+ return sym;
+
+not_found:
+ s = strncpy(sym, "<unknown>", size);
+
+ sym[size - 1] = '\0';
+
+ return s;
+}
--
1.7.0.4
next reply other threads:[~2011-05-11 20:09 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-11 20:09 Pekka Enberg [this message]
2011-05-11 20:22 ` [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3' Cyrill Gorcunov
2011-05-12 7:25 ` Ingo Molnar
2011-05-12 7:28 ` Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1305144589-21229-1-git-send-email-penberg@kernel.org \
--to=penberg@kernel.org \
--cc=asias.hejun@gmail.com \
--cc=avi@redhat.com \
--cc=gorcunov@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=levinsasha928@gmail.com \
--cc=mingo@elte.hu \
--cc=prasadjoshi124@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox