xref: /kvmtool/symbol.c (revision b0b42ba0140e77ab602d6960b1291873d34e59f5)
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