diff options
author | Pekka Enberg <penberg@kernel.org> | 2011-05-11 19:14:39 +0300 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2015-06-01 16:39:43 +0100 |
commit | b0b42ba0140e77ab602d6960b1291873d34e59f5 (patch) | |
tree | 120b69098443cecac7746225e44430d18d16464d /symbol.c | |
parent | 3780b3d5e7c7e02fa8465e6ac761a79e5cf0a817 (diff) | |
download | kvmtool-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.c | 98 |
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; +} |