* [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3'
@ 2011-05-11 20:09 Pekka Enberg
2011-05-11 20:22 ` Cyrill Gorcunov
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Pekka Enberg @ 2011-05-11 20:09 UTC (permalink / raw)
To: kvm
Cc: Pekka Enberg, Asias He, Avi Kivity, Cyrill Gorcunov, Ingo Molnar,
Prasad Joshi, Sasha Levin
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
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3'
2011-05-11 20:09 [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3' Pekka Enberg
@ 2011-05-11 20:22 ` Cyrill Gorcunov
2011-05-12 7:25 ` Ingo Molnar
2011-05-12 7:28 ` Ingo Molnar
2 siblings, 0 replies; 4+ messages in thread
From: Cyrill Gorcunov @ 2011-05-11 20:22 UTC (permalink / raw)
To: Pekka Enberg
Cc: kvm, Asias He, Avi Kivity, Ingo Molnar, Prasad Joshi, Sasha Levin
On 05/12/2011 12:09 AM, Pekka Enberg wrote:
> 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:
>
FWIW, works pretty well for me. Probably we need some -e option for vmlinux path in future.
--
Cyrill
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3'
2011-05-11 20:09 [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3' Pekka Enberg
2011-05-11 20:22 ` Cyrill Gorcunov
@ 2011-05-12 7:25 ` Ingo Molnar
2011-05-12 7:28 ` Ingo Molnar
2 siblings, 0 replies; 4+ messages in thread
From: Ingo Molnar @ 2011-05-12 7:25 UTC (permalink / raw)
To: Pekka Enberg
Cc: kvm, Asias He, Avi Kivity, Cyrill Gorcunov, Prasad Joshi,
Sasha Levin
* Pekka Enberg <penberg@kernel.org> wrote:
> 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)
Hm, it does not work here:
rip: [<ffffffff8103921f>] <unknown>
While ../../vmlinux definitely has it:
ffffffff810391d9 <default_idle>:
ffffffff8103921f: eb 01 jmp ffffffff81039222 <default_idle+0x49>
Does libbfd require debug symbols? That's sad as i almost never use debug
symbols.
It would be nice to import the relevant elflib magic from tools/perf/.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3'
2011-05-11 20:09 [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3' Pekka Enberg
2011-05-11 20:22 ` Cyrill Gorcunov
2011-05-12 7:25 ` Ingo Molnar
@ 2011-05-12 7:28 ` Ingo Molnar
2 siblings, 0 replies; 4+ messages in thread
From: Ingo Molnar @ 2011-05-12 7:28 UTC (permalink / raw)
To: Pekka Enberg
Cc: kvm, Asias He, Avi Kivity, Cyrill Gorcunov, Prasad Joshi,
Sasha Levin
Another suggestion: would anyone be interested in adding a 'kvm debug' command
that does the kill -3 magic?
Initially it could be something very simple like:
int cmd_debug()
{
system("kill -3 $(pidof kvm)");
}
:-)
as i always have to remember this sequence to debug the guest - while typing
'kvm debug' would be a no-brainer.
(Maybe make it 'kvm debug guest', to keep the 'kvm debug' namespace clean.)
Thanks,
Ingo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-05-12 7:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-11 20:09 [PATCH] kvm tools: Lookup symbol based on RIP for 'kill -3' Pekka Enberg
2011-05-11 20:22 ` Cyrill Gorcunov
2011-05-12 7:25 ` Ingo Molnar
2011-05-12 7:28 ` Ingo Molnar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox