xref: /freebsd/usr.bin/gprof/kernel.c (revision 3ff369fed2a08f32dda232c10470b949bef9489f)
1 #ifndef lint
2 static const char rcsid[] =
3   "$FreeBSD$";
4 #endif /* not lint */
5 
6 #include <sys/param.h>
7 #include <sys/linker.h>
8 #include <sys/sysctl.h>
9 #include <sys/errno.h>
10 
11 #include <err.h>
12 #include <stdlib.h>
13 
14 #include "gprof.h"
15 
16 /* Things which get -E excluded by default. */
17 static char	*excludes[] = { ".mcount", "_mcleanup", NULL };
18 
19 int
20 kernel_getnfile(const char *unused, char ***defaultEs)
21 {
22 	char *namelist;
23 	size_t len;
24 	char *name;
25 
26 	if (sysctlbyname("kern.function_list", NULL, &len, NULL, 0) == -1)
27 		err(1, "sysctlbyname: function_list size");
28 	for (;;) {
29 		namelist = malloc(len);
30 		if (namelist == NULL)
31 			err(1, "malloc");
32 		if (sysctlbyname("kern.function_list", namelist, &len, NULL,
33 		   0) == 0)
34 			break;
35 		if (errno == ENOMEM)
36 			free(namelist);
37 		else
38 			err(1, "sysctlbyname: function_list");
39 	}
40 	nname = 0;
41 	for (name = namelist; *name != '\0'; name += strlen(name) + 1)
42 		nname++;
43 	/* Allocate memory for them, plus a terminating entry. */
44 	if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL)
45 		errx(1, "Insufficient memory for symbol table");
46 	npe = nl;
47 	for (name = namelist; *name != '\0'; name += strlen(name) + 1) {
48 		struct kld_sym_lookup ksl;
49 
50 		ksl.version = sizeof(ksl);
51 		ksl.symname = name;
52 		if (kldsym(0, KLDSYM_LOOKUP, &ksl))
53 			err(1, "kldsym(%s)", name);
54 		/* aflag not supported */
55 		if (uflag && strchr(name, '.') != NULL)
56 			continue;
57 		npe->value = ksl.symvalue;
58 		npe->name = name;
59 		npe++;
60 	}
61 	npe->value = -1;
62 
63 	*defaultEs = excludes;
64 }
65