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