diff options
author | green <green@FreeBSD.org> | 2001-10-30 15:54:09 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 2001-10-30 15:54:09 +0000 |
commit | 85a9f299f9ff18dd7fee037e0aee7e70d3971e7e (patch) | |
tree | 3af54369ee3af34acc584ccf59baf1a0dc95e078 /usr.bin/gprof/kernel.c | |
parent | 0bacb7acb24b620b0199d06b1a081160742a8cd5 (diff) | |
download | FreeBSD-src-85a9f299f9ff18dd7fee037e0aee7e70d3971e7e.zip FreeBSD-src-85a9f299f9ff18dd7fee037e0aee7e70d3971e7e.tar.gz |
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
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; +} |