Bug 171678 - [dtrace] dtrace -h doesn't work when io.d is installed
Summary: [dtrace] dtrace -h doesn't work when io.d is installed
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: George V. Neville-Neil
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-09-16 07:00 UTC by Mark Johnston
Modified: 2013-12-29 17:13 UTC (History)
0 users

See Also:


Attachments
dtrace_depends_on_sysctl.patch (1.75 KB, patch)
2012-12-15 06:34 UTC, Mark Johnston
no flags Details | Diff
patch (1.85 KB, patch)
2013-01-24 19:35 UTC, Mark Johnston
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Johnston 2012-09-16 07:00:27 UTC
When running dtrace -h, I get the following unintuitive error message:

$ dtrace -h -s perldtrace.d
dtrace: failed to compile script perldtrace.d: "/usr/lib/dtrace/regs_x86.d", line 2: type redeclared: struct devinfo

This error doesn't occur if I run it without -h, which doesn't make much sense since the scripts in /usr/lib/dtrace/ are processed regardless.

Fix: 

The root of the problem is the "#pragma D depends_on provider" in /usr/lib/dtrace/io.d. When dtrace sees that directive, it calls a DTRACEIOC_PROVIDER ioctl on /dev/dtrace/dtrace with the appropriate provider argument ("io" in this case) to verify that that provider really is available.

Turns out that the -h (and -G) option sets the DTRACE_O_NODEV flag, which basically means "don't open /dev/dtrace/dtrace or /dev/dtrace/fasttrap." This allows dtrace -h to be used without needing root privileges. But obviously we need to open /dev/dtrace/dtrace for the reason mentioned above, and dtrace aborts because it can't call the ioctl.

For now, I'm working around this by just removing /usr/lib/dtrace/io.d - I don't need it at the moment. I'm not sure what the right fix is. Probably the error message could also be improved in this case, but I haven't really looked into that.
Comment 1 Mark Johnston 2012-09-16 07:20:46 UTC
I should also point out that simply removing the depends_on directive in
io.d is a sufficient workaround. Just make sure dtio.ko is loaded I
guess. :)

-Mark
Comment 2 Mark Johnston 2012-12-15 06:34:08 UTC
I've attached a patch with an actual fix. Specific, this changes
libdtrace to first look for providers from the debug.dtrace.providers
sysctl. This doesn't require the user to be root, so dtrace -h works as
expected.

Here's an easy test case (for CURRENT) to reproduce the original problem:

$ cat probe.d
provider test {
        probe testprobe();
};
$ dtrace -h -s probe.d
dtrace: failed to compile script probe.d: "/usr/lib/dtrace/regs_x86.d", line 2: type redeclared: struct devinfo
$

As I mentioned, this is caused by the depends_on pragma in io.d. The
same problem comes up if a "depends_on provider" pragma is added to
probe.d.

Thanks,
-Mark
Comment 3 kenji.rikitake 2013-01-13 00:16:27 UTC
This patch (dtrace_depends_on_sysctl.patch)
was required when I built the Port lang/erlang
(Erlang/OTP R15B03-1) with the dtrace option enabled.
I suggest this patch should be merged
into the STABLE branch ASAP.

My test environment:
FreeBSD minimax.priv.k2r.org 9.1-STABLE FreeBSD 9.1-STABLE #14
r245019: Fri Jan  4 11:08:18 JST 2013
root@minimax.priv.k2r.org:/usr/obj/usr/src/sys/MINIMAX  amd64

And the Ports tree svn revision was r310207.

Regards,
Kenji Rikitake
Comment 4 Mark Johnston freebsd_committer freebsd_triage 2013-01-24 18:34:11 UTC
State Changed
From-To: open->analyzed

I believe gnn@ is taking a look at this. 


Comment 5 Mark Johnston freebsd_committer freebsd_triage 2013-01-24 18:34:11 UTC
Responsible Changed
From-To: freebsd-bugs->gnn

I believe gnn@ is taking a look at this.
Comment 6 Mark Johnston freebsd_committer freebsd_triage 2013-01-24 19:35:59 UTC
Here's a slightly updated version of the last patch - this changes the
new code so that dt_lookup_provider() is still called if we can't find
the provider in the debug.dtrace.providers sysctl.

Thanks,
-Mark
Comment 7 George V. Neville-Neil freebsd_committer freebsd_triage 2013-03-28 20:15:27 UTC
State Changed
From-To: analyzed->patched

I have committed what I think is a fix to HEAD, in the form of an 
updated io.d.  Please test aand let me know.
Comment 8 George V. Neville-Neil freebsd_committer freebsd_triage 2013-03-28 20:23:18 UTC
State Changed
From-To: patched->analyzed

Need to apply a different patch moving back to analyzed for the moment.
Comment 9 George V. Neville-Neil freebsd_committer freebsd_triage 2013-03-28 20:26:55 UTC
State Changed
From-To: analyzed->patched

Apply the latest patch to address this from the reporter.
Comment 10 dfilter service freebsd_committer freebsd_triage 2013-03-28 20:31:16 UTC
Author: gnn
Date: Thu Mar 28 20:31:03 2013
New Revision: 248848
URL: http://svnweb.freebsd.org/changeset/base/248848

Log:
  Commit a patch that fixes a problem in the #pragma statement when searching
  for and loading dependent modules.  This addresses a bug seen with
  io.d where it was being doubly included.
  
  PR:		171678
  Submitted by:	 Mark Johnston
  MFC after:	2 weeks

Modified:
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c	Thu Mar 28 20:27:01 2013	(r248847)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c	Thu Mar 28 20:31:03 2013	(r248848)
@@ -241,6 +241,8 @@ dt_pragma_depends(const char *prname, dt
 	int found;
 	dt_lib_depend_t *dld;
 	char lib[MAXPATHLEN];
+	size_t plen;
+	char *provs, *cpy, *tok;
 
 	if (cnp == NULL || nnp == NULL ||
 	    cnp->dn_kind != DT_NODE_IDENT || nnp->dn_kind != DT_NODE_IDENT) {
@@ -248,9 +250,31 @@ dt_pragma_depends(const char *prname, dt
 		    "<class> <name>\n", prname);
 	}
 
-	if (strcmp(cnp->dn_string, "provider") == 0)
-		found = dt_provider_lookup(dtp, nnp->dn_string) != NULL;
-	else if (strcmp(cnp->dn_string, "module") == 0) {
+	if (strcmp(cnp->dn_string, "provider") == 0) {
+		/*
+		 * First try to get the provider list using the
+		 * debug.dtrace.providers sysctl, since that'll work even if
+		 * we're not running as root.
+		 */
+		provs = NULL;
+		if (sysctlbyname("debug.dtrace.providers", NULL, &plen, NULL, 0) ||
+		    ((provs = dt_alloc(dtp, plen)) == NULL) ||
+		    sysctlbyname("debug.dtrace.providers", provs, &plen, NULL, 0))
+			found = dt_provider_lookup(dtp, nnp->dn_string) != NULL;
+		else {
+			found = B_FALSE;
+			for (cpy = provs; (tok = strsep(&cpy, " ")) != NULL; )
+				if (strcmp(tok, nnp->dn_string) == 0) {
+					found = B_TRUE;
+					break;
+				}
+			if (found == B_FALSE)
+				found = dt_provider_lookup(dtp,
+				    nnp->dn_string) != NULL;
+		}
+		if (provs != NULL)
+			dt_free(dtp, provs);
+	} else if (strcmp(cnp->dn_string, "module") == 0) {
 		dt_module_t *mp = dt_module_lookup_by_name(dtp, nnp->dn_string);
 		found = mp != NULL && dt_module_getctf(dtp, mp) != NULL;
 	} else if (strcmp(cnp->dn_string, "library") == 0) {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 11 dfilter service freebsd_committer freebsd_triage 2013-06-17 16:42:39 UTC
Author: gnn
Date: Mon Jun 17 15:42:21 2013
New Revision: 251857
URL: http://svnweb.freebsd.org/changeset/base/251857

Log:
  MFC: 248848
  
  Commit a patch that fixes a problem in the #pragma statement when searching
  for and loading dependent modules.  This addresses a bug seen with
  io.d where it was being doubly included.
  
  PR:		171678
  Submitted by:	 Mark Johnston

Modified:
  stable/9/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c
Directory Properties:
  stable/9/cddl/contrib/opensolaris/lib/libdtrace/common/   (props changed)

Modified: stable/9/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c	Mon Jun 17 15:34:22 2013	(r251856)
+++ stable/9/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c	Mon Jun 17 15:42:21 2013	(r251857)
@@ -241,6 +241,8 @@ dt_pragma_depends(const char *prname, dt
 	int found;
 	dt_lib_depend_t *dld;
 	char lib[MAXPATHLEN];
+	size_t plen;
+	char *provs, *cpy, *tok;
 
 	if (cnp == NULL || nnp == NULL ||
 	    cnp->dn_kind != DT_NODE_IDENT || nnp->dn_kind != DT_NODE_IDENT) {
@@ -248,9 +250,31 @@ dt_pragma_depends(const char *prname, dt
 		    "<class> <name>\n", prname);
 	}
 
-	if (strcmp(cnp->dn_string, "provider") == 0)
-		found = dt_provider_lookup(dtp, nnp->dn_string) != NULL;
-	else if (strcmp(cnp->dn_string, "module") == 0) {
+	if (strcmp(cnp->dn_string, "provider") == 0) {
+		/*
+		 * First try to get the provider list using the
+		 * debug.dtrace.providers sysctl, since that'll work even if
+		 * we're not running as root.
+		 */
+		provs = NULL;
+		if (sysctlbyname("debug.dtrace.providers", NULL, &plen, NULL, 0) ||
+		    ((provs = dt_alloc(dtp, plen)) == NULL) ||
+		    sysctlbyname("debug.dtrace.providers", provs, &plen, NULL, 0))
+			found = dt_provider_lookup(dtp, nnp->dn_string) != NULL;
+		else {
+			found = B_FALSE;
+			for (cpy = provs; (tok = strsep(&cpy, " ")) != NULL; )
+				if (strcmp(tok, nnp->dn_string) == 0) {
+					found = B_TRUE;
+					break;
+				}
+			if (found == B_FALSE)
+				found = dt_provider_lookup(dtp,
+				    nnp->dn_string) != NULL;
+		}
+		if (provs != NULL)
+			dt_free(dtp, provs);
+	} else if (strcmp(cnp->dn_string, "module") == 0) {
 		dt_module_t *mp = dt_module_lookup_by_name(dtp, nnp->dn_string);
 		found = mp != NULL && dt_module_getctf(dtp, mp) != NULL;
 	} else if (strcmp(cnp->dn_string, "library") == 0) {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 12 Mark Johnston freebsd_committer freebsd_triage 2013-12-29 17:13:04 UTC
State Changed
From-To: patched->closed

The fix for this PR has been committed and MFCed.