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