freebsd-skq/usr.bin/gprof/kernel.c
Brian Feldman 3fc980b135 Add -K support to gprof(1), which enables dynamic symbol resolution from
the currently-running kernel (and supercedes an executable file argument
given).  With this change, properly-compiled KLD modules are now
able to be profiled.

Obtained from:	NAI Labs CBOSS project
Funded by:	DARPA
2001-10-30 15:54:09 +00:00

65 lines
1.5 KiB
C

#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#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;
}