summaryrefslogtreecommitdiffstats
path: root/usr.bin/gprof
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2001-10-30 15:54:09 +0000
committergreen <green@FreeBSD.org>2001-10-30 15:54:09 +0000
commit85a9f299f9ff18dd7fee037e0aee7e70d3971e7e (patch)
tree3af54369ee3af34acc584ccf59baf1a0dc95e078 /usr.bin/gprof
parent0bacb7acb24b620b0199d06b1a081160742a8cd5 (diff)
downloadFreeBSD-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')
-rw-r--r--usr.bin/gprof/Makefile3
-rw-r--r--usr.bin/gprof/gprof.111
-rw-r--r--usr.bin/gprof/gprof.c8
-rw-r--r--usr.bin/gprof/gprof.h4
-rw-r--r--usr.bin/gprof/kernel.c64
5 files changed, 87 insertions, 3 deletions
diff --git a/usr.bin/gprof/Makefile b/usr.bin/gprof/Makefile
index 29291cc..cc5a276 100644
--- a/usr.bin/gprof/Makefile
+++ b/usr.bin/gprof/Makefile
@@ -1,8 +1,9 @@
# @(#)Makefile 8.1 (Berkeley) 6/29/93
+# $FreeBSD$
PROG= gprof
SRCS= gprof.c aout.c arcs.c dfn.c elf.c lookup.c ${MACHINE_ARCH}.c hertz.c \
- printgprof.c printlist.c
+ printgprof.c printlist.c kernel.c
beforeinstall:
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
diff --git a/usr.bin/gprof/gprof.1 b/usr.bin/gprof/gprof.1
index f421221..fa45baa 100644
--- a/usr.bin/gprof/gprof.1
+++ b/usr.bin/gprof/gprof.1
@@ -208,6 +208,17 @@ option may be given.
Only one pair of routine names may be given with each
.Fl k
option.
+.It Fl K
+Gather information about symbols from the currently-running kernel using the
+.Xr sysctl 3
+and
+.Xr kldsym 2
+interfaces.
+This forces the
+.Pa a.out
+argument to be ignored, and allows for symbols in
+.Xr kld 4
+modules to be used.
.It Fl l
Suppresses the printing of the call-graph profile.
.It Fl L
diff --git a/usr.bin/gprof/gprof.c b/usr.bin/gprof/gprof.c
index dfb1e2c..79dafc7 100644
--- a/usr.bin/gprof/gprof.c
+++ b/usr.bin/gprof/gprof.c
@@ -125,6 +125,9 @@ main(argc, argv)
addlist( ktolist , *++argv );
kflag = TRUE;
break;
+ case 'K':
+ Kflag = TRUE;
+ break;
case 'l':
lflag = 1;
Lflag = 0;
@@ -162,8 +165,9 @@ main(argc, argv)
/*
* get information from the executable file.
*/
- if (elf_getnfile(a_outname, &defaultEs) == -1 &&
- aout_getnfile(a_outname, &defaultEs) == -1)
+ if ((Kflag && kernel_getnfile(a_outname, &defaultEs) == -1) ||
+ (elf_getnfile(a_outname, &defaultEs) == -1 &&
+ aout_getnfile(a_outname, &defaultEs) == -1))
errx(1, "%s: bad format", a_outname);
/*
* sort symbol table.
diff --git a/usr.bin/gprof/gprof.h b/usr.bin/gprof/gprof.h
index 3a7c54b..ee0976e 100644
--- a/usr.bin/gprof/gprof.h
+++ b/usr.bin/gprof/gprof.h
@@ -238,6 +238,7 @@ bool Eflag; /* functions excluded with time */
bool fflag; /* specific functions requested */
bool Fflag; /* functions requested with time */
bool kflag; /* arcs to be deleted */
+bool Kflag; /* use the running kernel for symbols */
bool sflag; /* sum multiple gmon.out files */
bool uflag; /* suppress symbols hidden from C */
bool zflag; /* zero time/called functions, too */
@@ -295,6 +296,9 @@ int elf_getnfile(const char *, char ***);
getpfile();
gprofheader();
gprofline();
+*/
+int kernel_getnfile(const char *, char ***);
+/*
main();
*/
unsigned long max();
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;
+}
OpenPOWER on IntegriCloud