1*b0b42ba0SPekka Enberg #include "kvm/symbol.h" 2*b0b42ba0SPekka Enberg 3*b0b42ba0SPekka Enberg #include "kvm/kvm.h" 4*b0b42ba0SPekka Enberg 5*b0b42ba0SPekka Enberg #include <stdlib.h> 6*b0b42ba0SPekka Enberg #include <string.h> 7*b0b42ba0SPekka Enberg #include <stdio.h> 8*b0b42ba0SPekka Enberg #include <bfd.h> 9*b0b42ba0SPekka Enberg 10*b0b42ba0SPekka Enberg static bfd *abfd; 11*b0b42ba0SPekka Enberg 12*b0b42ba0SPekka Enberg void symbol__init(const char *vmlinux) 13*b0b42ba0SPekka Enberg { 14*b0b42ba0SPekka Enberg if (!vmlinux) 15*b0b42ba0SPekka Enberg return; 16*b0b42ba0SPekka Enberg 17*b0b42ba0SPekka Enberg bfd_init(); 18*b0b42ba0SPekka Enberg 19*b0b42ba0SPekka Enberg abfd = bfd_openr(vmlinux, NULL); 20*b0b42ba0SPekka Enberg } 21*b0b42ba0SPekka Enberg 22*b0b42ba0SPekka Enberg static asymbol *lookup(asymbol **symbols, int nr_symbols, const char *symbol_name) 23*b0b42ba0SPekka Enberg { 24*b0b42ba0SPekka Enberg int i; 25*b0b42ba0SPekka Enberg 26*b0b42ba0SPekka Enberg for (i = 0; i < nr_symbols; i++) { 27*b0b42ba0SPekka Enberg asymbol *symbol = symbols[i]; 28*b0b42ba0SPekka Enberg 29*b0b42ba0SPekka Enberg if (!strcmp(bfd_asymbol_name(symbol), symbol_name)) 30*b0b42ba0SPekka Enberg return symbol; 31*b0b42ba0SPekka Enberg } 32*b0b42ba0SPekka Enberg 33*b0b42ba0SPekka Enberg return NULL; 34*b0b42ba0SPekka Enberg } 35*b0b42ba0SPekka Enberg 36*b0b42ba0SPekka Enberg char *symbol__lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size) 37*b0b42ba0SPekka Enberg { 38*b0b42ba0SPekka Enberg const char *filename; 39*b0b42ba0SPekka Enberg bfd_vma sym_offset; 40*b0b42ba0SPekka Enberg bfd_vma sym_start; 41*b0b42ba0SPekka Enberg asection *section; 42*b0b42ba0SPekka Enberg unsigned int line; 43*b0b42ba0SPekka Enberg const char *func; 44*b0b42ba0SPekka Enberg long symtab_size; 45*b0b42ba0SPekka Enberg asymbol *symbol; 46*b0b42ba0SPekka Enberg asymbol **syms; 47*b0b42ba0SPekka Enberg int nr_syms; 48*b0b42ba0SPekka Enberg char *s; 49*b0b42ba0SPekka Enberg 50*b0b42ba0SPekka Enberg if (!abfd) 51*b0b42ba0SPekka Enberg goto not_found; 52*b0b42ba0SPekka Enberg 53*b0b42ba0SPekka Enberg if (!bfd_check_format(abfd, bfd_object)) 54*b0b42ba0SPekka Enberg goto not_found; 55*b0b42ba0SPekka Enberg 56*b0b42ba0SPekka Enberg symtab_size = bfd_get_symtab_upper_bound(abfd); 57*b0b42ba0SPekka Enberg if (!symtab_size) 58*b0b42ba0SPekka Enberg goto not_found; 59*b0b42ba0SPekka Enberg 60*b0b42ba0SPekka Enberg syms = malloc(symtab_size); 61*b0b42ba0SPekka Enberg if (!syms) 62*b0b42ba0SPekka Enberg goto not_found; 63*b0b42ba0SPekka Enberg 64*b0b42ba0SPekka Enberg nr_syms = bfd_canonicalize_symtab(abfd, syms); 65*b0b42ba0SPekka Enberg 66*b0b42ba0SPekka Enberg section = bfd_get_section_by_name(abfd, ".debug_aranges"); 67*b0b42ba0SPekka Enberg if (!section) 68*b0b42ba0SPekka Enberg goto not_found; 69*b0b42ba0SPekka Enberg 70*b0b42ba0SPekka Enberg if (!bfd_find_nearest_line(abfd, section, NULL, addr, &filename, &func, &line)) 71*b0b42ba0SPekka Enberg goto not_found; 72*b0b42ba0SPekka Enberg 73*b0b42ba0SPekka Enberg if (!func) 74*b0b42ba0SPekka Enberg goto not_found; 75*b0b42ba0SPekka Enberg 76*b0b42ba0SPekka Enberg symbol = lookup(syms, nr_syms, func); 77*b0b42ba0SPekka Enberg if (!symbol) 78*b0b42ba0SPekka Enberg goto not_found; 79*b0b42ba0SPekka Enberg 80*b0b42ba0SPekka Enberg sym_start = bfd_asymbol_value(symbol); 81*b0b42ba0SPekka Enberg 82*b0b42ba0SPekka Enberg sym_offset = addr - sym_start; 83*b0b42ba0SPekka Enberg 84*b0b42ba0SPekka Enberg snprintf(sym, size, "%s+%llx (%s:%i)", func, (long long) sym_offset, filename, line); 85*b0b42ba0SPekka Enberg 86*b0b42ba0SPekka Enberg sym[size - 1] = '\0'; 87*b0b42ba0SPekka Enberg 88*b0b42ba0SPekka Enberg free(syms); 89*b0b42ba0SPekka Enberg 90*b0b42ba0SPekka Enberg return sym; 91*b0b42ba0SPekka Enberg 92*b0b42ba0SPekka Enberg not_found: 93*b0b42ba0SPekka Enberg s = strncpy(sym, "<unknown>", size); 94*b0b42ba0SPekka Enberg 95*b0b42ba0SPekka Enberg sym[size - 1] = '\0'; 96*b0b42ba0SPekka Enberg 97*b0b42ba0SPekka Enberg return s; 98*b0b42ba0SPekka Enberg } 99