summaryrefslogtreecommitdiffstats
path: root/cddl
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2016-04-10 01:25:48 +0000
committermarkj <markj@FreeBSD.org>2016-04-10 01:25:48 +0000
commit61ede4b2ecba0e7719312562eabb9f52e4d7ecfd (patch)
treefd9e73d2a0133421cd4a8af938b3c790bd50e959 /cddl
parent7a70a2258262a6c228b3b459dfeb426e68e58e32 (diff)
downloadFreeBSD-src-61ede4b2ecba0e7719312562eabb9f52e4d7ecfd.zip
FreeBSD-src-61ede4b2ecba0e7719312562eabb9f52e4d7ecfd.tar.gz
Implement support for boot-time DTrace.
This allows one to enable DTrace probes relatively early during boot, during SI_SUB_DTRACE_ANON, before dtrace(1) can invoked. The desired enabling is created using dtrace -A, which writes a /boot/dtrace.dof file and uses nextboot(8) to ensure that DTrace kernel modules are loaded and that the DOF file describing the enabling is loaded by loader(8) during the subsequent boot. The trace output can then be fetched with dtrace -a. With this commit, boot-time DTrace is only functional on i386 and amd64: on other architectures, the high-resolution timer frequency is initialized during SI_SUB_CLOCKS and is thus not available when the anonymous tracing state is initialized. On x86, the TSC is used and is thus available earlier. MFC after: 1 month Relnotes: yes
Diffstat (limited to 'cddl')
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/dtrace.c71
1 files changed, 55 insertions, 16 deletions
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c
index d8bdaa6..d065cdc 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c
+++ b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c
@@ -50,6 +50,9 @@
#ifdef illumos
#include <libproc.h>
#endif
+#ifdef __FreeBSD__
+#include <spawn.h>
+#endif
typedef struct dtrace_cmd {
void (*dc_func)(struct dtrace_cmd *); /* function to compile arg */
@@ -397,7 +400,41 @@ dof_prune(const char *fname)
free(buf);
}
-#ifdef illumos
+#ifdef __FreeBSD__
+/*
+ * Use nextboot(8) to tell the loader to load DTrace kernel modules during
+ * the next boot of the system. The nextboot(8) configuration is removed during
+ * boot, so it will not persist indefinitely.
+ */
+static void
+bootdof_add(void)
+{
+ char * const nbargv[] = {
+ "nextboot", "-a",
+ "-e", "dtraceall_load=\"YES\"",
+ "-e", "dtrace_dof_load=\"YES\"",
+ "-e", "dtrace_dof_name=\"/boot/dtrace.dof\"",
+ "-e", "dtrace_dof_type=\"dtrace_dof\"",
+ NULL,
+ };
+ pid_t child;
+ int err, status;
+
+ err = posix_spawnp(&child, "nextboot", NULL, NULL, nbargv,
+ NULL);
+ if (err != 0) {
+ error("failed to execute nextboot: %s", strerror(err));
+ exit(E_ERROR);
+ }
+
+ if (waitpid(child, &status, 0) != child)
+ fatal("waiting for nextboot");
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ error("nextboot returned with status %d", status);
+ exit(E_ERROR);
+ }
+}
+#else
static void
etcsystem_prune(void)
{
@@ -508,7 +545,7 @@ etcsystem_add(void)
error("added forceload directives to %s\n", g_ofile);
}
-#endif /* illumos */
+#endif /* !__FreeBSD__ */
static void
print_probe_info(const dtrace_probeinfo_t *p)
@@ -643,24 +680,24 @@ anon_prog(const dtrace_cmd_t *dcp, dof_hdr_t *dof, int n)
p = (uchar_t *)dof;
q = p + dof->dofh_loadsz;
-#ifdef illumos
- oprintf("dof-data-%d=0x%x", n, *p++);
-
- while (p < q)
- oprintf(",0x%x", *p++);
-
- oprintf(";\n");
-#else
+#ifdef __FreeBSD__
/*
- * On FreeBSD, the DOF data is handled as a kernel environment (kenv)
- * string. We use two hex characters per DOF byte.
+ * On FreeBSD, the DOF file is read directly during boot - just write
+ * two hex characters per byte.
*/
- oprintf("dof-data-%d=%02x", n, *p++);
+ oprintf("dof-data-%d=", n);
while (p < q)
oprintf("%02x", *p++);
oprintf("\n");
+#else
+ oprintf("dof-data-%d=0x%x", n, *p++);
+
+ while (p < q)
+ oprintf(",0x%x", *p++);
+
+ oprintf(";\n");
#endif
dtrace_dof_destroy(g_dtp, dof);
@@ -1725,8 +1762,7 @@ main(int argc, char *argv[])
#else
/*
* On FreeBSD, anonymous DOF data is written to
- * the DTrace DOF file that the boot loader will
- * read if booting with the DTrace option.
+ * the DTrace DOF file.
*/
g_ofile = "/boot/dtrace.dof";
#endif
@@ -1765,7 +1801,10 @@ main(int argc, char *argv[])
* that itself contains a #pragma D option quiet.
*/
error("saved anonymous enabling in %s\n", g_ofile);
-#ifdef illumos
+
+#ifdef __FreeBSD__
+ bootdof_add();
+#else
etcsystem_add();
error("run update_drv(1M) or reboot to enable changes\n");
#endif
OpenPOWER on IntegriCloud