aboutsummaryrefslogtreecommitdiffstats
path: root/symbol.c
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2011-05-11 19:14:39 +0300
committerWill Deacon <will.deacon@arm.com>2015-06-01 16:39:43 +0100
commitb0b42ba0140e77ab602d6960b1291873d34e59f5 (patch)
tree120b69098443cecac7746225e44430d18d16464d /symbol.c
parent3780b3d5e7c7e02fa8465e6ac761a79e5cf0a817 (diff)
downloadkvmtool-b0b42ba0140e77ab602d6960b1291873d34e59f5.tar.gz
kvm tools: Lookup symbol based on RIP for 'kill -3'
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>
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/symbol.c b/symbol.c
new file mode 100644
index 00000000..56dd346c
--- /dev/null
+++ b/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;
+}