199112Sobrien#include <sys/cdefs.h>
299112Sobrien__FBSDID("$FreeBSD: releng/10.3/usr.bin/gprof/kernel.c 246783 2013-02-14 08:16:03Z charnier $");
385739Sgreen
485739Sgreen#include <sys/param.h>
585739Sgreen#include <sys/linker.h>
685739Sgreen#include <sys/sysctl.h>
785739Sgreen#include <sys/errno.h>
885739Sgreen
985739Sgreen#include <err.h>
1085739Sgreen#include <stdlib.h>
11129657Sstefanf#include <string.h>
1285739Sgreen
1385739Sgreen#include "gprof.h"
1485739Sgreen
1585739Sgreen/* Things which get -E excluded by default. */
1685739Sgreenstatic char	*excludes[] = { ".mcount", "_mcleanup", NULL };
1785739Sgreen
1885739Sgreenint
19246783Scharnierkernel_getnfile(const char *unused __unused, char ***defaultEs)
2085739Sgreen{
2185739Sgreen	char *namelist;
2285739Sgreen	size_t len;
2385739Sgreen	char *name;
2485739Sgreen
2585739Sgreen	if (sysctlbyname("kern.function_list", NULL, &len, NULL, 0) == -1)
2685739Sgreen		err(1, "sysctlbyname: function_list size");
2785739Sgreen	for (;;) {
2885739Sgreen		namelist = malloc(len);
2985739Sgreen		if (namelist == NULL)
3085739Sgreen			err(1, "malloc");
3185739Sgreen		if (sysctlbyname("kern.function_list", namelist, &len, NULL,
3285739Sgreen		   0) == 0)
3385739Sgreen			break;
3485739Sgreen		if (errno == ENOMEM)
3585739Sgreen			free(namelist);
3685739Sgreen		else
3785739Sgreen			err(1, "sysctlbyname: function_list");
3885739Sgreen	}
3985739Sgreen	nname = 0;
4085739Sgreen	for (name = namelist; *name != '\0'; name += strlen(name) + 1)
4185739Sgreen		nname++;
4285739Sgreen	/* Allocate memory for them, plus a terminating entry. */
4385739Sgreen	if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL)
4485739Sgreen		errx(1, "Insufficient memory for symbol table");
4585739Sgreen	npe = nl;
4685739Sgreen	for (name = namelist; *name != '\0'; name += strlen(name) + 1) {
4785739Sgreen		struct kld_sym_lookup ksl;
4885739Sgreen
4985739Sgreen		ksl.version = sizeof(ksl);
5085739Sgreen		ksl.symname = name;
5185739Sgreen		if (kldsym(0, KLDSYM_LOOKUP, &ksl))
5285739Sgreen			err(1, "kldsym(%s)", name);
5385739Sgreen		/* aflag not supported */
5485739Sgreen		if (uflag && strchr(name, '.') != NULL)
5585739Sgreen			continue;
5685739Sgreen		npe->value = ksl.symvalue;
5785739Sgreen		npe->name = name;
5885739Sgreen		npe++;
5985739Sgreen	}
6085739Sgreen	npe->value = -1;
6185739Sgreen
6285739Sgreen	*defaultEs = excludes;
63136175Sgreen	return (0);
6485739Sgreen}
65