summaryrefslogtreecommitdiffstats
path: root/usr.bin/gprof/kernel.c
blob: fc140877909c5f66574eb97086d78eac567901ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#include <sys/param.h>
#include <sys/linker.h>
#include <sys/sysctl.h>
#include <sys/errno.h>

#include <err.h>
#include <stdlib.h>

#include "gprof.h"

/* Things which get -E excluded by default. */
static char	*excludes[] = { ".mcount", "_mcleanup", NULL };

int
kernel_getnfile(const char *unused, char ***defaultEs)
{
	char *namelist;
	size_t len;
	char *name;

	if (sysctlbyname("kern.function_list", NULL, &len, NULL, 0) == -1)
		err(1, "sysctlbyname: function_list size");
	for (;;) {
		namelist = malloc(len);
		if (namelist == NULL)
			err(1, "malloc");
		if (sysctlbyname("kern.function_list", namelist, &len, NULL,
		   0) == 0)
			break;
		if (errno == ENOMEM)
			free(namelist);
		else
			err(1, "sysctlbyname: function_list");
	}
	nname = 0;
	for (name = namelist; *name != '\0'; name += strlen(name) + 1)
		nname++;
	/* Allocate memory for them, plus a terminating entry. */
	if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL)
		errx(1, "Insufficient memory for symbol table");
	npe = nl;
	for (name = namelist; *name != '\0'; name += strlen(name) + 1) {
		struct kld_sym_lookup ksl;

		ksl.version = sizeof(ksl);
		ksl.symname = name;
		if (kldsym(0, KLDSYM_LOOKUP, &ksl))
			err(1, "kldsym(%s)", name);
		/* aflag not supported */
		if (uflag && strchr(name, '.') != NULL)
			continue;
		npe->value = ksl.symvalue;
		npe->name = name;
		npe++;
	}
	npe->value = -1;

	*defaultEs = excludes;
}
OpenPOWER on IntegriCloud