diff options
Diffstat (limited to 'usr.bin/gprof/kernel.c')
-rw-r--r-- | usr.bin/gprof/kernel.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/usr.bin/gprof/kernel.c b/usr.bin/gprof/kernel.c new file mode 100644 index 0000000..c8df0d0 --- /dev/null +++ b/usr.bin/gprof/kernel.c @@ -0,0 +1,64 @@ +#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; +} |