diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
index c76cecf494b5..9b02e982fe0d 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
@@ -22,6 +22,7 @@
 /*
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -98,6 +99,8 @@ STRFUNC(inet_ntoa((ipaddr_t *)alloca(sizeof (ipaddr_t))))
 STRFUNC(inet_ntoa6((in6_addr_t *)alloca(sizeof (in6_addr_t))))
 STRFUNC(inet_ntop(AF_INET, (void *)alloca(sizeof (ipaddr_t))))
 INTFUNC(getf(0))
+INTFUNC(strtoll("0x12EE5D5", 16))
+STRFUNC(json("{\"systemtap\": false}", "systemtap"))
 
 BEGIN
 /subr == DIF_SUBR_MAX + 1/
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d
new file mode 100644
index 000000000000..4600811d95b9
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d
@@ -0,0 +1,179 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Joyent, Inc.  All rights reserved.
+ */
+
+/*
+ * General functional tests of JSON parser for json().
+ */
+
+#pragma D option quiet
+#pragma D option strsize=1k
+
+#define	TST(name)				\
+	printf("\ntst |%s|\n", name)
+#define	IN2(vala, valb)				\
+	in = strjoin(vala, valb);		\
+	printf("in  |%s|\n", in)
+#define	IN(val)					\
+	in = val;				\
+	printf("in  |%s|\n", in)
+#define	SEL(ss)					\
+	out = json(in, ss);			\
+	printf("sel |%s|\nout |%s|\n", ss,	\
+	    out != NULL ? out : "<NULL>")
+
+BEGIN
+{
+	TST("empty array");
+	IN("[]");
+	SEL("0");
+
+	TST("one-element array: integer");
+	IN("[1]");
+	SEL("0");
+	SEL("1");
+	SEL("100");
+	SEL("-1");
+
+	TST("one-element array: hex integer (not in spec, not supported)");
+	IN("[0x1000]");
+	SEL("0");
+
+	TST("one-element array: float");
+	IN("[1.5001]");
+	SEL("0");
+
+	TST("one-element array: float + exponent");
+	IN("[16.3e10]");
+	SEL("0");
+
+	TST("one-element array: integer + whitespace");
+	IN("[ \t   5\t]");
+	SEL("0");
+
+	TST("one-element array: integer + exponent + whitespace");
+	IN("[ \t    \t 16E10  \t ]");
+	SEL("0");
+
+	TST("one-element array: string");
+	IN("[\"alpha\"]");
+	SEL("0");
+
+	TST("alternative first-element indexing");
+	IN("[1,5,10,15,20]");
+	SEL("[0]");
+	SEL("[3]");
+	SEL("[4]");
+	SEL("[5]");
+
+	TST("one-element array: object");
+	IN("[ { \"first\": true, \"second\": false }]");
+	SEL("0.first");
+	SEL("0.second");
+	SEL("0.third");
+
+	TST("many-element array: integers");
+	IN("[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]");
+	SEL("10"); /* F(10) = 55 */
+	SEL("14"); /* F(14) = 377 */
+	SEL("19");
+
+	TST("many-element array: multiple types");
+	IN2("[\"string\",32,true,{\"a\":9,\"b\":false},100.3e10,false,200.5,",
+	    "{\"key\":\"val\"},null]");
+	SEL("0");
+	SEL("0.notobject");
+	SEL("1");
+	SEL("2");
+	SEL("3");
+	SEL("3.a");
+	SEL("3.b");
+	SEL("3.c");
+	SEL("4");
+	SEL("5");
+	SEL("6");
+	SEL("7");
+	SEL("7.key");
+	SEL("7.key.notobject");
+	SEL("7.nonexist");
+	SEL("8");
+	SEL("9");
+
+	TST("many-element array: multiple types + whitespace");
+	IN2("\n[\t\"string\" ,\t32 , true\t,\t {\"a\":  9,\t\"b\": false},\t\t",
+	    "100.3e10, false, 200.5,{\"key\" \t:\n \"val\"},\t\t null ]\t\t");
+	SEL("0");
+	SEL("0.notobject");
+	SEL("1");
+	SEL("2");
+	SEL("3");
+	SEL("3.a");
+	SEL("3.b");
+	SEL("3.c");
+	SEL("4");
+	SEL("5");
+	SEL("6");
+	SEL("7");
+	SEL("7.key");
+	SEL("7.key.notobject");
+	SEL("7.nonexist");
+	SEL("8");
+	SEL("9");
+
+	TST("two-element array: various string escape codes");
+	IN2("[\"abcd \\\" \\\\ \\/ \\b \\f \\n \\r \\t \\u0000 \\uf00F \", ",
+	    "\"final\"]");
+	SEL("0");
+	SEL("1");
+
+	TST("three-element array: broken escape code");
+	IN("[\"fine here\", \"dodgey \\u00AZ\", \"wont get here\"]");
+	SEL("0");
+	SEL("1");
+	SEL("2");
+
+	TST("nested objects");
+	IN2("{ \"top\": { \"mid\"  : { \"legs\": \"feet\" }, \"number\": 9, ",
+	    "\"array\":[0,1,{\"a\":true,\"bb\":[1,2,false,{\"x\":\"yz\"}]}]}}");
+	SEL("top");
+	SEL("fargo");
+	SEL("top.mid");
+	SEL("top.centre");
+	SEL("top.mid.legs");
+	SEL("top.mid.number");
+	SEL("top.mid.array");
+	SEL("top.number");
+	SEL("top.array");
+	SEL("top.array[0]");
+	SEL("top.array[1]");
+	SEL("top.array[2]");
+	SEL("top.array[2].a");
+	SEL("top.array[2].b");
+	SEL("top.array[2].bb");
+	SEL("top.array[2].bb[0]");
+	SEL("top.array[2].bb[1]");
+	SEL("top.array[2].bb[2]");
+	SEL("top.array[2].bb[3]");
+	SEL("top.array[2].bb[3].x");
+	SEL("top.array[2].bb[3].x.nofurther");
+	SEL("top.array[2].bb[4]");
+	SEL("top.array[3]");
+
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d.out
new file mode 100644
index 000000000000..a857ab91d831
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d.out
@@ -0,0 +1,218 @@
+
+tst |empty array|
+in  |[]|
+sel |0|
+out |<NULL>|
+
+tst |one-element array: integer|
+in  |[1]|
+sel |0|
+out |1|
+sel |1|
+out |<NULL>|
+sel |100|
+out |<NULL>|
+sel |-1|
+out |<NULL>|
+
+tst |one-element array: hex integer (not in spec, not supported)|
+in  |[0x1000]|
+sel |0|
+out |<NULL>|
+
+tst |one-element array: float|
+in  |[1.5001]|
+sel |0|
+out |1.5001|
+
+tst |one-element array: float + exponent|
+in  |[16.3e10]|
+sel |0|
+out |16.3e10|
+
+tst |one-element array: integer + whitespace|
+in  |[ 	   5	]|
+sel |0|
+out |5|
+
+tst |one-element array: integer + exponent + whitespace|
+in  |[ 	    	 16E10  	 ]|
+sel |0|
+out |16E10|
+
+tst |one-element array: string|
+in  |["alpha"]|
+sel |0|
+out |alpha|
+
+tst |alternative first-element indexing|
+in  |[1,5,10,15,20]|
+sel |[0]|
+out |1|
+sel |[3]|
+out |15|
+sel |[4]|
+out |20|
+sel |[5]|
+out |<NULL>|
+
+tst |one-element array: object|
+in  |[ { "first": true, "second": false }]|
+sel |0.first|
+out |true|
+sel |0.second|
+out |false|
+sel |0.third|
+out |<NULL>|
+
+tst |many-element array: integers|
+in  |[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]|
+sel |10|
+out |55|
+sel |14|
+out |377|
+sel |19|
+out |<NULL>|
+
+tst |many-element array: multiple types|
+in  |["string",32,true,{"a":9,"b":false},100.3e10,false,200.5,{"key":"val"},null]|
+sel |0|
+out |string|
+sel |0.notobject|
+out |<NULL>|
+sel |1|
+out |32|
+sel |2|
+out |true|
+sel |3|
+out |{"a":9,"b":false}|
+sel |3.a|
+out |9|
+sel |3.b|
+out |false|
+sel |3.c|
+out |<NULL>|
+sel |4|
+out |100.3e10|
+sel |5|
+out |false|
+sel |6|
+out |200.5|
+sel |7|
+out |{"key":"val"}|
+sel |7.key|
+out |val|
+sel |7.key.notobject|
+out |<NULL>|
+sel |7.nonexist|
+out |<NULL>|
+sel |8|
+out |null|
+sel |9|
+out |<NULL>|
+
+tst |many-element array: multiple types + whitespace|
+in  |
+[	"string" ,	32 , true	,	 {"a":  9,	"b": false},		100.3e10, false, 200.5,{"key" 	:
+ "val"},		 null ]		|
+sel |0|
+out |string|
+sel |0.notobject|
+out |<NULL>|
+sel |1|
+out |32|
+sel |2|
+out |true|
+sel |3|
+out |{"a":  9,	"b": false}|
+sel |3.a|
+out |9|
+sel |3.b|
+out |false|
+sel |3.c|
+out |<NULL>|
+sel |4|
+out |100.3e10|
+sel |5|
+out |false|
+sel |6|
+out |200.5|
+sel |7|
+out |{"key" 	:
+ "val"}|
+sel |7.key|
+out |val|
+sel |7.key.notobject|
+out |<NULL>|
+sel |7.nonexist|
+out |<NULL>|
+sel |8|
+out |null|
+sel |9|
+out |<NULL>|
+
+tst |two-element array: various string escape codes|
+in  |["abcd \" \\ \/ \b \f \n \r \t \u0000 \uf00F ", "final"]|
+sel |0|
+out |abcd \" \\ \/ \b \f \n \r \t \u0000 \uf00F |
+sel |1|
+out |final|
+
+tst |three-element array: broken escape code|
+in  |["fine here", "dodgey \u00AZ", "wont get here"]|
+sel |0|
+out |fine here|
+sel |1|
+out |<NULL>|
+sel |2|
+out |<NULL>|
+
+tst |nested objects|
+in  |{ "top": { "mid"  : { "legs": "feet" }, "number": 9, "array":[0,1,{"a":true,"bb":[1,2,false,{"x":"yz"}]}]}}|
+sel |top|
+out |{ "mid"  : { "legs": "feet" }, "number": 9, "array":[0,1,{"a":true,"bb":[1,2,false,{"x":"yz"}]}]}|
+sel |fargo|
+out |<NULL>|
+sel |top.mid|
+out |{ "legs": "feet" }|
+sel |top.centre|
+out |<NULL>|
+sel |top.mid.legs|
+out |feet|
+sel |top.mid.number|
+out |<NULL>|
+sel |top.mid.array|
+out |<NULL>|
+sel |top.number|
+out |9|
+sel |top.array|
+out |[0,1,{"a":true,"bb":[1,2,false,{"x":"yz"}]}]|
+sel |top.array[0]|
+out |0|
+sel |top.array[1]|
+out |1|
+sel |top.array[2]|
+out |{"a":true,"bb":[1,2,false,{"x":"yz"}]}|
+sel |top.array[2].a|
+out |true|
+sel |top.array[2].b|
+out |<NULL>|
+sel |top.array[2].bb|
+out |[1,2,false,{"x":"yz"}]|
+sel |top.array[2].bb[0]|
+out |1|
+sel |top.array[2].bb[1]|
+out |2|
+sel |top.array[2].bb[2]|
+out |false|
+sel |top.array[2].bb[3]|
+out |{"x":"yz"}|
+sel |top.array[2].bb[3].x|
+out |yz|
+sel |top.array[2].bb[3].x.nofurther|
+out |<NULL>|
+sel |top.array[2].bb[4]|
+out |<NULL>|
+sel |top.array[3]|
+out |<NULL>|
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d
new file mode 100644
index 000000000000..6aa50b9ad02b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d
@@ -0,0 +1,51 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Joyent, Inc.  All rights reserved.
+ */
+
+/*
+ * ASSERTION:
+ *   json() run time must be bounded above by strsize.  This test makes strsize
+ *   small and deliberately overflows it to prove we bail and return NULL in
+ *   the event that we run off the end of the string.
+ *
+ */
+
+#pragma D option quiet
+#pragma D option strsize=18
+
+BEGIN
+{
+	in = "{\"a\":         1024}"; /* length == 19 */
+	out = json(in, "a");
+	printf("|%s|\n%s\n\n", in, out != NULL ? out : "<NULL>");
+
+	in = "{\"a\": 1024}"; /* length == 11 */
+	out = json(in, "a");
+	printf("|%s|\n%s\n\n", in, out != NULL ? out : "<NULL>");
+
+	in = "{\"a\":false,\"b\":true}"; /* length == 20 */
+	out = json(in, "b");
+	printf("|%s|\n%s\n\n", in, out != NULL ? out : "<NULL>");
+
+	in = "{\"a\":false,\"b\":20}"; /* length == 18 */
+	out = json(in, "b");
+	printf("|%s|\n%s\n\n", in, out != NULL ? out : "<NULL>");
+
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d.out
new file mode 100644
index 000000000000..7f1d79b6fedb
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d.out
@@ -0,0 +1,13 @@
+|{"a":         1024|
+<NULL>
+
+|{"a": 1024}|
+1024
+
+|{"a":false,"b":tru|
+<NULL>
+
+|{"a":false,"b":20}|
+20
+
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.c b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.c
new file mode 100644
index 000000000000..307106d903b5
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.c
@@ -0,0 +1,61 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 (c), Joyent, Inc.  All rights reserved.
+ */
+
+#include <sys/sdt.h>
+#include "usdt.h"
+
+#define	FMT	"{" \
+		"  \"sizes\": [ \"first\", 2, %f ]," \
+		"  \"index\": %d," \
+		"  \"facts\": {" \
+		"    \"odd\": \"%s\"," \
+		"    \"even\": \"%s\"" \
+		"  }," \
+		"  \"action\": \"%s\"" \
+		"}\n"
+
+int
+waiting(volatile int *a)
+{
+	return (*a);
+}
+
+int
+main(int argc, char **argv)
+{
+	volatile int a = 0;
+	int idx;
+	double size = 250.5;
+
+	while (waiting(&a) == 0)
+		continue;
+
+	for (idx = 0; idx < 10; idx++) {
+		char *odd, *even, *json, *action;
+
+		size *= 1.78;
+		odd = idx % 2 == 1 ? "true" : "false";
+		even = idx % 2 == 0 ? "true" : "false";
+		action = idx == 7 ? "ignore" : "print";
+
+		asprintf(&json, FMT, size, idx, odd, even, action);
+		BUNYAN_FAKE_LOG_DEBUG(json);
+		free(json);
+	}
+
+	BUNYAN_FAKE_LOG_DEBUG("{\"finished\": true}");
+
+	return (0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d
new file mode 100644
index 000000000000..f0fbdd5cabab
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d
@@ -0,0 +1,65 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
+
+#pragma D option strsize=4k
+#pragma D option quiet
+#pragma D option destructive
+
+/*
+ * This test reads a JSON string from a USDT probe, roughly simulating the
+ * primary motivating use case for the json() subroutine: filtering
+ * JSON-formatted log messages from a logging subsystem like node-bunyan.
+ */
+
+pid$1:a.out:waiting:entry
+{
+	this->value = (int *)alloca(sizeof (int));
+	*this->value = 1;
+	copyout(this->value, arg0, sizeof (int));
+}
+
+bunyan*$1:::log-*
+{
+	this->j = copyinstr(arg0);
+}
+
+bunyan*$1:::log-*
+/json(this->j, "finished") == NULL && json(this->j, "action") != "ignore"/
+{
+	this->index = strtoll(json(this->j, "index"));
+	this->size = json(this->j, "sizes[2]");
+	this->odd = json(this->j, "facts.odd");
+	this->even = json(this->j, "facts.even");
+	printf("[%d] sz %s odd %s even %s\n", this->index, this->size,
+	    this->odd, this->even);
+}
+
+bunyan*$1:::log-*
+/json(this->j, "finished") != NULL/
+{
+	printf("FINISHED!\n");
+	exit(0);
+}
+
+tick-10s
+{
+	printf("ERROR: Timed out before finish message!\n");
+	exit(1);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d.out
new file mode 100644
index 000000000000..c7f58bb535dd
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d.out
@@ -0,0 +1,11 @@
+[0] sz 445.890000 odd false even true
+[1] sz 793.684200 odd true even false
+[2] sz 1412.757876 odd false even true
+[3] sz 2514.709019 odd true even false
+[4] sz 4476.182054 odd false even true
+[5] sz 7967.604057 odd true even false
+[6] sz 14182.335221 odd false even true
+[8] sz 44935.310914 odd false even true
+[9] sz 79984.853427 odd true even false
+FINISHED!
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/usdt.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/usdt.d
new file mode 100644
index 000000000000..1a4fc87f60f4
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/usdt.d
@@ -0,0 +1,27 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Joyent, Inc.  All rights reserved.
+ */
+
+/*
+ * Sets up a fake node-bunyan-like USDT provider for use from C.
+ */
+
+provider bunyan_fake {
+	probe log__trace(char *msg);
+	probe log__debug(char *msg);
+	probe log__info(char *msg);
+	probe log__warn(char *msg);
+	probe log__error(char *msg);
+	probe log__fatal(char *msg);
+};
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
index ae4934cdeb34..da9bb4c6c6b3 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
@@ -22,8 +22,8 @@
 #
 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
 
 ppriv -s A=basic,dtrace_proc,dtrace_user $$
 
@@ -31,7 +31,7 @@ ppriv -s A=basic,dtrace_proc,dtrace_user $$
 
 BEGIN {
 	errorcount = 0;
-	expected_errorcount = 23;
+	expected_errorcount = 27;
 }
 
 BEGIN { trace(mutex_owned(&`pidlock)); }
@@ -55,6 +55,8 @@ BEGIN { trace(strtok(`initname, "/")); }
 BEGIN { trace(strtok(NULL, "/")); }
 BEGIN { trace(strtok("foo/bar", `initname)); }
 BEGIN { trace(strtok(NULL, `initname)); }
+BEGIN { trace(strtoll(`initname)); }
+BEGIN { trace(strtoll(`initname, 10)); }
 BEGIN { trace(substr(`initname, 2, 3)); }
 
 BEGIN { trace(ddi_pathname(`top_devinfo, 1)); }
@@ -63,6 +65,9 @@ BEGIN { trace(strjoin("foo", `initname)); }
 BEGIN { trace(dirname(`initname)); }
 BEGIN { trace(cleanpath(`initname)); }
 
+BEGIN { j = "{\"/sbin/init\":\"uh oh\"}"; trace(json(j, `initname)); }
+BEGIN { trace(json(`initname, "x")); }
+
 ERROR {
 	errorcount++;
 }
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooLarge.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooLarge.d
new file mode 100644
index 000000000000..4d6b5af75b55
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooLarge.d
@@ -0,0 +1,35 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * ASSERTION:
+ *   The largest base we will accept is Base 36 -- i.e. using all of 0-9 and
+ *   A-Z as numerals.
+ *
+ * SECTION: Actions and Subroutines/strtoll()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	printf("%d\n", strtoll("0", 37));
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooSmall.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooSmall.d
new file mode 100644
index 000000000000..de56b50e9eda
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooSmall.d
@@ -0,0 +1,34 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * ASSERTION:
+ *   The smallest base we will accept is Base 2.
+ *
+ * SECTION: Actions and Subroutines/strtoll()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	printf("%d\n", strtoll("0", 1));
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d
new file mode 100644
index 000000000000..0b1812a53ce0
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d
@@ -0,0 +1,66 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * ASSERTION:
+ *   Test the strtoll() subroutine.
+ *
+ * SECTION: Actions and Subroutines/strtoll()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+
+	/* minimum base (2) and maximum base (36): */
+	printf("%d\n", strtoll("0", 2));
+	printf("%d\n", strtoll("1", 36));
+
+	/* simple tests: */
+	printf("%d\n", strtoll("0x20", 16));
+	printf("%d\n", strtoll("-32", 10));
+	printf("%d\n", strtoll("010", 8));
+	printf("%d\n", strtoll("101010", 2));
+
+	/* INT64_MIN and INT64_MAX: */
+	printf("%d\n", strtoll("9223372036854775807"));
+	printf("%d\n", strtoll("-9223372036854775808"));
+	printf("%d\n", strtoll("0777777777777777777777", 8));
+	printf("%d\n", strtoll("-01000000000000000000000", 8));
+
+	/* wrapping: */
+	printf("%d\n", strtoll("1000000000000000000000", 8));
+	printf("%d\n", strtoll("-1000000000000000000001", 8));
+
+	/* hex without prefix: */
+	printf("%d\n", strtoll("baddcafe", 16));
+
+	/* stopping at first out-of-base character: */
+	printf("%d\n", strtoll("12j", 10));
+	printf("%d\n", strtoll("102", 2));
+
+	/* base 36: */
+	printf("%d\n", strtoll("-0DTrace4EverZ", 36));
+
+	/* base 10 is assumed: */
+	printf("%d\n", strtoll("1985"));
+	printf("%d\n", strtoll("-2012"));
+
+	/* empty string: */
+	printf("%d\n", strtoll(""));
+
+	exit(0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d.out
new file mode 100644
index 000000000000..d12eb9c1973b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d.out
@@ -0,0 +1,20 @@
+0
+1
+32
+-32
+8
+42
+9223372036854775807
+-9223372036854775808
+9223372036854775807
+-9223372036854775808
+-9223372036854775808
+9223372036854775807
+3135097598
+12
+2
+-1819882045752187535
+1985
+-2012
+0
+
diff --git a/cddl/contrib/opensolaris/common/util/strtolctype.h b/cddl/contrib/opensolaris/common/util/strtolctype.h
new file mode 100644
index 000000000000..a1d18367d345
--- /dev/null
+++ b/cddl/contrib/opensolaris/common/util/strtolctype.h
@@ -0,0 +1,79 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*	Copyright (c) 1988 AT&T	*/
+/*	  All Rights Reserved  	*/
+
+#ifndef	_COMMON_UTIL_CTYPE_H
+#define	_COMMON_UTIL_CTYPE_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * This header file contains a collection of macros that the strtou?ll?
+ * functions in common/util use to test characters.  What we need is a kernel
+ * version of ctype.h.
+ *
+ * NOTE: These macros are used within several DTrace probe context functions.
+ * They must not be altered to make function calls or perform actions not
+ * safe in probe context.
+ */
+
+#if defined(sun) &&	(defined(_KERNEL) || defined(_BOOT))
+
+#define	isalnum(ch)	(isalpha(ch) || isdigit(ch))
+#define	isalpha(ch)	(isupper(ch) || islower(ch))
+#define	isdigit(ch)	((ch) >= '0' && (ch) <= '9')
+#define	islower(ch)	((ch) >= 'a' && (ch) <= 'z')
+#define	isspace(ch)	(((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \
+			((ch) == '\t') || ((ch) == '\f'))
+#define	isupper(ch)	((ch) >= 'A' && (ch) <= 'Z')
+#define	isxdigit(ch)	(isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
+			((ch) >= 'A' && (ch) <= 'F'))
+
+#endif	/* _KERNEL || _BOOT */
+
+#define	DIGIT(x)	\
+	(isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
+
+#define	MBASE	('z' - 'a' + 1 + 10)
+
+/*
+ * The following macro is a version of isalnum() that limits alphabetic
+ * characters to the ranges a-z and A-Z; locale dependent characters will not
+ * return 1.  The members of a-z and A-Z are assumed to be in ascending order
+ * and contiguous.
+ */
+#define	lisalnum(x)	\
+	(isdigit(x) || ((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _COMMON_UTIL_CTYPE_H */
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
index 6a195016c4cd..92f3f27bae14 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
@@ -123,8 +123,9 @@
 #define	DT_VERS_1_9	DT_VERSION_NUMBER(1, 9, 0)
 #define	DT_VERS_1_9_1	DT_VERSION_NUMBER(1, 9, 1)
 #define	DT_VERS_1_10	DT_VERSION_NUMBER(1, 10, 0)
-#define	DT_VERS_LATEST	DT_VERS_1_10
-#define	DT_VERS_STRING	"Sun D 1.10"
+#define	DT_VERS_1_11	DT_VERSION_NUMBER(1, 11, 0)
+#define	DT_VERS_LATEST	DT_VERS_1_11
+#define	DT_VERS_STRING	"Sun D 1.11"
 
 const dt_version_t _dtrace_versions[] = {
 	DT_VERS_1_0,	/* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -147,6 +148,7 @@ const dt_version_t _dtrace_versions[] = {
 	DT_VERS_1_9,	/* D API 1.9 */
 	DT_VERS_1_9_1,	/* D API 1.9.1 */
 	DT_VERS_1_10,	/* D API 1.10 */
+	DT_VERS_1_11,	/* D API 1.11 */
 	0
 };
 
@@ -301,6 +303,8 @@ static const dt_ident_t _dtrace_globals[] = {
 	DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },
 { "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,
 	&dt_idops_type, "uint_t" },
+{ "json", DT_IDENT_FUNC, 0, DIF_SUBR_JSON, DT_ATTR_STABCMN, DT_VERS_1_11,
+	&dt_idops_func, "string(const char *, const char *)" },
 { "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
 	&dt_idops_func, "stack(...)" },
 { "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -452,6 +456,8 @@ static const dt_ident_t _dtrace_globals[] = {
 	&dt_idops_func, "string(const char *, const char *)" },
 { "strtok", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOK, DT_ATTR_STABCMN, DT_VERS_1_1,
 	&dt_idops_func, "string(const char *, const char *)" },
+{ "strtoll", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOLL, DT_ATTR_STABCMN, DT_VERS_1_11,
+	&dt_idops_func, "int64_t(const char *, [int])" },
 { "substr", DT_IDENT_FUNC, 0, DIF_SUBR_SUBSTR, DT_ATTR_STABCMN, DT_VERS_1_1,
 	&dt_idops_func, "string(const char *, int, [int])" },
 { "sum", DT_IDENT_AGGFUNC, 0, DTRACEAGG_SUM, DT_ATTR_STABCMN, DT_VERS_1_0,
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
index 8b35923868bc..e84b79cf18e4 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
@@ -111,6 +111,7 @@
 #include <sys/zone.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include "strtolctype.h"
 
 /* FreeBSD includes: */
 #if !defined(sun)
@@ -966,6 +967,58 @@ dtrace_vcanload(void *src, dtrace_diftype_t *type, dtrace_mstate_t *mstate,
 	return (dtrace_canload((uintptr_t)src, sz, mstate, vstate));
 }
 
+/*
+ * Convert a string to a signed integer using safe loads.
+ *
+ * NOTE: This function uses various macros from strtolctype.h to manipulate
+ * digit values, etc -- these have all been checked to ensure they make
+ * no additional function calls.
+ */
+static int64_t
+dtrace_strtoll(char *input, int base, size_t limit)
+{
+	uintptr_t pos = (uintptr_t)input;
+	int64_t val = 0;
+	int x;
+	boolean_t neg = B_FALSE;
+	char c, cc, ccc;
+	uintptr_t end = pos + limit;
+
+	/*
+	 * Consume any whitespace preceding digits.
+	 */
+	while ((c = dtrace_load8(pos)) == ' ' || c == '\t')
+		pos++;
+
+	/*
+	 * Handle an explicit sign if one is present.
+	 */
+	if (c == '-' || c == '+') {
+		if (c == '-')
+			neg = B_TRUE;
+		c = dtrace_load8(++pos);
+	}
+
+	/*
+	 * Check for an explicit hexadecimal prefix ("0x" or "0X") and skip it
+	 * if present.
+	 */
+	if (base == 16 && c == '0' && ((cc = dtrace_load8(pos + 1)) == 'x' ||
+	    cc == 'X') && isxdigit(ccc = dtrace_load8(pos + 2))) {
+		pos += 2;
+		c = ccc;
+	}
+
+	/*
+	 * Read in contiguous digits until the first non-digit character.
+	 */
+	for (; pos < end && c != '\0' && lisalnum(c) && (x = DIGIT(c)) < base;
+	    c = dtrace_load8(++pos))
+		val = val * base + x;
+
+	return (neg ? -val : val);
+}
+
 /*
  * Compare two strings using safe loads.
  */
@@ -3469,6 +3522,463 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
 	}
 }
 
+
+typedef enum dtrace_json_state {
+	DTRACE_JSON_REST = 1,
+	DTRACE_JSON_OBJECT,
+	DTRACE_JSON_STRING,
+	DTRACE_JSON_STRING_ESCAPE,
+	DTRACE_JSON_STRING_ESCAPE_UNICODE,
+	DTRACE_JSON_COLON,
+	DTRACE_JSON_COMMA,
+	DTRACE_JSON_VALUE,
+	DTRACE_JSON_IDENTIFIER,
+	DTRACE_JSON_NUMBER,
+	DTRACE_JSON_NUMBER_FRAC,
+	DTRACE_JSON_NUMBER_EXP,
+	DTRACE_JSON_COLLECT_OBJECT
+} dtrace_json_state_t;
+
+/*
+ * This function possesses just enough knowledge about JSON to extract a single
+ * value from a JSON string and store it in the scratch buffer.  It is able
+ * to extract nested object values, and members of arrays by index.
+ *
+ * elemlist is a list of JSON keys, stored as packed NUL-terminated strings, to
+ * be looked up as we descend into the object tree.  e.g.
+ *
+ *    foo[0].bar.baz[32] --> "foo" NUL "0" NUL "bar" NUL "baz" NUL "32" NUL
+ *       with nelems = 5.
+ *
+ * The run time of this function must be bounded above by strsize to limit the
+ * amount of work done in probe context.  As such, it is implemented as a
+ * simple state machine, reading one character at a time using safe loads
+ * until we find the requested element, hit a parsing error or run off the
+ * end of the object or string.
+ *
+ * As there is no way for a subroutine to return an error without interrupting
+ * clause execution, we simply return NULL in the event of a missing key or any
+ * other error condition.  Each NULL return in this function is commented with
+ * the error condition it represents -- parsing or otherwise.
+ *
+ * The set of states for the state machine closely matches the JSON
+ * specification (http://json.org/).  Briefly:
+ *
+ *   DTRACE_JSON_REST:
+ *     Skip whitespace until we find either a top-level Object, moving
+ *     to DTRACE_JSON_OBJECT; or an Array, moving to DTRACE_JSON_VALUE.
+ *
+ *   DTRACE_JSON_OBJECT:
+ *     Locate the next key String in an Object.  Sets a flag to denote
+ *     the next String as a key string and moves to DTRACE_JSON_STRING.
+ *
+ *   DTRACE_JSON_COLON:
+ *     Skip whitespace until we find the colon that separates key Strings
+ *     from their values.  Once found, move to DTRACE_JSON_VALUE.
+ *
+ *   DTRACE_JSON_VALUE:
+ *     Detects the type of the next value (String, Number, Identifier, Object
+ *     or Array) and routes to the states that process that type.  Here we also
+ *     deal with the element selector list if we are requested to traverse down
+ *     into the object tree.
+ *
+ *   DTRACE_JSON_COMMA:
+ *     Skip whitespace until we find the comma that separates key-value pairs
+ *     in Objects (returning to DTRACE_JSON_OBJECT) or values in Arrays
+ *     (similarly DTRACE_JSON_VALUE).  All following literal value processing
+ *     states return to this state at the end of their value, unless otherwise
+ *     noted.
+ *
+ *   DTRACE_JSON_NUMBER, DTRACE_JSON_NUMBER_FRAC, DTRACE_JSON_NUMBER_EXP:
+ *     Processes a Number literal from the JSON, including any exponent
+ *     component that may be present.  Numbers are returned as strings, which
+ *     may be passed to strtoll() if an integer is required.
+ *
+ *   DTRACE_JSON_IDENTIFIER:
+ *     Processes a "true", "false" or "null" literal in the JSON.
+ *
+ *   DTRACE_JSON_STRING, DTRACE_JSON_STRING_ESCAPE,
+ *   DTRACE_JSON_STRING_ESCAPE_UNICODE:
+ *     Processes a String literal from the JSON, whether the String denotes
+ *     a key, a value or part of a larger Object.  Handles all escape sequences
+ *     present in the specification, including four-digit unicode characters,
+ *     but merely includes the escape sequence without converting it to the
+ *     actual escaped character.  If the String is flagged as a key, we
+ *     move to DTRACE_JSON_COLON rather than DTRACE_JSON_COMMA.
+ *
+ *   DTRACE_JSON_COLLECT_OBJECT:
+ *     This state collects an entire Object (or Array), correctly handling
+ *     embedded strings.  If the full element selector list matches this nested
+ *     object, we return the Object in full as a string.  If not, we use this
+ *     state to skip to the next value at this level and continue processing.
+ *
+ * NOTE: This function uses various macros from strtolctype.h to manipulate
+ * digit values, etc -- these have all been checked to ensure they make
+ * no additional function calls.
+ */
+static char *
+dtrace_json(uint64_t size, uintptr_t json, char *elemlist, int nelems,
+    char *dest)
+{
+	dtrace_json_state_t state = DTRACE_JSON_REST;
+	int64_t array_elem = INT64_MIN;
+	int64_t array_pos = 0;
+	uint8_t escape_unicount = 0;
+	boolean_t string_is_key = B_FALSE;
+	boolean_t collect_object = B_FALSE;
+	boolean_t found_key = B_FALSE;
+	boolean_t in_array = B_FALSE;
+	uint32_t braces = 0, brackets = 0;
+	char *elem = elemlist;
+	char *dd = dest;
+	uintptr_t cur;
+
+	for (cur = json; cur < json + size; cur++) {
+		char cc = dtrace_load8(cur);
+		if (cc == '\0')
+			return (NULL);
+
+		switch (state) {
+		case DTRACE_JSON_REST:
+			if (isspace(cc))
+				break;
+
+			if (cc == '{') {
+				state = DTRACE_JSON_OBJECT;
+				break;
+			}
+
+			if (cc == '[') {
+				in_array = B_TRUE;
+				array_pos = 0;
+				array_elem = dtrace_strtoll(elem, 10, size);
+				found_key = array_elem == 0 ? B_TRUE : B_FALSE;
+				state = DTRACE_JSON_VALUE;
+				break;
+			}
+
+			/*
+			 * ERROR: expected to find a top-level object or array.
+			 */
+			return (NULL);
+		case DTRACE_JSON_OBJECT:
+			if (isspace(cc))
+				break;
+
+			if (cc == '"') {
+				state = DTRACE_JSON_STRING;
+				string_is_key = B_TRUE;
+				break;
+			}
+
+			/*
+			 * ERROR: either the object did not start with a key
+			 * string, or we've run off the end of the object
+			 * without finding the requested key.
+			 */
+			return (NULL);
+		case DTRACE_JSON_STRING:
+			if (cc == '\\') {
+				*dd++ = '\\';
+				state = DTRACE_JSON_STRING_ESCAPE;
+				break;
+			}
+
+			if (cc == '"') {
+				if (collect_object) {
+					/*
+					 * We don't reset the dest here, as
+					 * the string is part of a larger
+					 * object being collected.
+					 */
+					*dd++ = cc;
+					collect_object = B_FALSE;
+					state = DTRACE_JSON_COLLECT_OBJECT;
+					break;
+				}
+				*dd = '\0';
+				dd = dest; /* reset string buffer */
+				if (string_is_key) {
+					if (dtrace_strncmp(dest, elem,
+					    size) == 0)
+						found_key = B_TRUE;
+				} else if (found_key) {
+					if (nelems > 1) {
+						/*
+						 * We expected an object, not
+						 * this string.
+						 */
+						return (NULL);
+					}
+					return (dest);
+				}
+				state = string_is_key ? DTRACE_JSON_COLON :
+				    DTRACE_JSON_COMMA;
+				string_is_key = B_FALSE;
+				break;
+			}
+
+			*dd++ = cc;
+			break;
+		case DTRACE_JSON_STRING_ESCAPE:
+			*dd++ = cc;
+			if (cc == 'u') {
+				escape_unicount = 0;
+				state = DTRACE_JSON_STRING_ESCAPE_UNICODE;
+			} else {
+				state = DTRACE_JSON_STRING;
+			}
+			break;
+		case DTRACE_JSON_STRING_ESCAPE_UNICODE:
+			if (!isxdigit(cc)) {
+				/*
+				 * ERROR: invalid unicode escape, expected
+				 * four valid hexidecimal digits.
+				 */
+				return (NULL);
+			}
+
+			*dd++ = cc;
+			if (++escape_unicount == 4)
+				state = DTRACE_JSON_STRING;
+			break;
+		case DTRACE_JSON_COLON:
+			if (isspace(cc))
+				break;
+
+			if (cc == ':') {
+				state = DTRACE_JSON_VALUE;
+				break;
+			}
+
+			/*
+			 * ERROR: expected a colon.
+			 */
+			return (NULL);
+		case DTRACE_JSON_COMMA:
+			if (isspace(cc))
+				break;
+
+			if (cc == ',') {
+				if (in_array) {
+					state = DTRACE_JSON_VALUE;
+					if (++array_pos == array_elem)
+						found_key = B_TRUE;
+				} else {
+					state = DTRACE_JSON_OBJECT;
+				}
+				break;
+			}
+
+			/*
+			 * ERROR: either we hit an unexpected character, or
+			 * we reached the end of the object or array without
+			 * finding the requested key.
+			 */
+			return (NULL);
+		case DTRACE_JSON_IDENTIFIER:
+			if (islower(cc)) {
+				*dd++ = cc;
+				break;
+			}
+
+			*dd = '\0';
+			dd = dest; /* reset string buffer */
+
+			if (dtrace_strncmp(dest, "true", 5) == 0 ||
+			    dtrace_strncmp(dest, "false", 6) == 0 ||
+			    dtrace_strncmp(dest, "null", 5) == 0) {
+				if (found_key) {
+					if (nelems > 1) {
+						/*
+						 * ERROR: We expected an object,
+						 * not this identifier.
+						 */
+						return (NULL);
+					}
+					return (dest);
+				} else {
+					cur--;
+					state = DTRACE_JSON_COMMA;
+					break;
+				}
+			}
+
+			/*
+			 * ERROR: we did not recognise the identifier as one
+			 * of those in the JSON specification.
+			 */
+			return (NULL);
+		case DTRACE_JSON_NUMBER:
+			if (cc == '.') {
+				*dd++ = cc;
+				state = DTRACE_JSON_NUMBER_FRAC;
+				break;
+			}
+
+			if (cc == 'x' || cc == 'X') {
+				/*
+				 * ERROR: specification explicitly excludes
+				 * hexidecimal or octal numbers.
+				 */
+				return (NULL);
+			}
+
+			/* FALLTHRU */
+		case DTRACE_JSON_NUMBER_FRAC:
+			if (cc == 'e' || cc == 'E') {
+				*dd++ = cc;
+				state = DTRACE_JSON_NUMBER_EXP;
+				break;
+			}
+
+			if (cc == '+' || cc == '-') {
+				/*
+				 * ERROR: expect sign as part of exponent only.
+				 */
+				return (NULL);
+			}
+			/* FALLTHRU */
+		case DTRACE_JSON_NUMBER_EXP:
+			if (isdigit(cc) || cc == '+' || cc == '-') {
+				*dd++ = cc;
+				break;
+			}
+
+			*dd = '\0';
+			dd = dest; /* reset string buffer */
+			if (found_key) {
+				if (nelems > 1) {
+					/*
+					 * ERROR: We expected an object, not
+					 * this number.
+					 */
+					return (NULL);
+				}
+				return (dest);
+			}
+
+			cur--;
+			state = DTRACE_JSON_COMMA;
+			break;
+		case DTRACE_JSON_VALUE:
+			if (isspace(cc))
+				break;
+
+			if (cc == '{' || cc == '[') {
+				if (nelems > 1 && found_key) {
+					in_array = cc == '[' ? B_TRUE : B_FALSE;
+					/*
+					 * If our element selector directs us
+					 * to descend into this nested object,
+					 * then move to the next selector
+					 * element in the list and restart the
+					 * state machine.
+					 */
+					while (*elem != '\0')
+						elem++;
+					elem++; /* skip the inter-element NUL */
+					nelems--;
+					dd = dest;
+					if (in_array) {
+						state = DTRACE_JSON_VALUE;
+						array_pos = 0;
+						array_elem = dtrace_strtoll(
+						    elem, 10, size);
+						found_key = array_elem == 0 ?
+						    B_TRUE : B_FALSE;
+					} else {
+						found_key = B_FALSE;
+						state = DTRACE_JSON_OBJECT;
+					}
+					break;
+				}
+
+				/*
+				 * Otherwise, we wish to either skip this
+				 * nested object or return it in full.
+				 */
+				if (cc == '[')
+					brackets = 1;
+				else
+					braces = 1;
+				*dd++ = cc;
+				state = DTRACE_JSON_COLLECT_OBJECT;
+				break;
+			}
+
+			if (cc == '"') {
+				state = DTRACE_JSON_STRING;
+				break;
+			}
+
+			if (islower(cc)) {
+				/*
+				 * Here we deal with true, false and null.
+				 */
+				*dd++ = cc;
+				state = DTRACE_JSON_IDENTIFIER;
+				break;
+			}
+
+			if (cc == '-' || isdigit(cc)) {
+				*dd++ = cc;
+				state = DTRACE_JSON_NUMBER;
+				break;
+			}
+
+			/*
+			 * ERROR: unexpected character at start of value.
+			 */
+			return (NULL);
+		case DTRACE_JSON_COLLECT_OBJECT:
+			if (cc == '\0')
+				/*
+				 * ERROR: unexpected end of input.
+				 */
+				return (NULL);
+
+			*dd++ = cc;
+			if (cc == '"') {
+				collect_object = B_TRUE;
+				state = DTRACE_JSON_STRING;
+				break;
+			}
+
+			if (cc == ']') {
+				if (brackets-- == 0) {
+					/*
+					 * ERROR: unbalanced brackets.
+					 */
+					return (NULL);
+				}
+			} else if (cc == '}') {
+				if (braces-- == 0) {
+					/*
+					 * ERROR: unbalanced braces.
+					 */
+					return (NULL);
+				}
+			} else if (cc == '{') {
+				braces++;
+			} else if (cc == '[') {
+				brackets++;
+			}
+
+			if (brackets == 0 && braces == 0) {
+				if (found_key) {
+					*dd = '\0';
+					return (dest);
+				}
+				dd = dest; /* reset string buffer */
+				state = DTRACE_JSON_COMMA;
+			}
+			break;
+		}
+	}
+	return (NULL);
+}
+
 /*
  * Emulate the execution of DTrace ID subroutines invoked by the call opcode.
  * Notice that we don't bother validating the proper number of arguments or
@@ -4265,6 +4775,65 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
 		break;
 	}
 
+	case DIF_SUBR_JSON: {
+		uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
+		uintptr_t json = tupregs[0].dttk_value;
+		size_t jsonlen = dtrace_strlen((char *)json, size);
+		uintptr_t elem = tupregs[1].dttk_value;
+		size_t elemlen = dtrace_strlen((char *)elem, size);
+
+		char *dest = (char *)mstate->dtms_scratch_ptr;
+		char *elemlist = (char *)mstate->dtms_scratch_ptr + jsonlen + 1;
+		char *ee = elemlist;
+		int nelems = 1;
+		uintptr_t cur;
+
+		if (!dtrace_canload(json, jsonlen + 1, mstate, vstate) ||
+		    !dtrace_canload(elem, elemlen + 1, mstate, vstate)) {
+			regs[rd] = 0;
+			break;
+		}
+
+		if (!DTRACE_INSCRATCH(mstate, jsonlen + 1 + elemlen + 1)) {
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
+			regs[rd] = 0;
+			break;
+		}
+
+		/*
+		 * Read the element selector and split it up into a packed list
+		 * of strings.
+		 */
+		for (cur = elem; cur < elem + elemlen; cur++) {
+			char cc = dtrace_load8(cur);
+
+			if (cur == elem && cc == '[') {
+				/*
+				 * If the first element selector key is
+				 * actually an array index then ignore the
+				 * bracket.
+				 */
+				continue;
+			}
+
+			if (cc == ']')
+				continue;
+
+			if (cc == '.' || cc == '[') {
+				nelems++;
+				cc = '\0';
+			}
+
+			*ee++ = cc;
+		}
+		*ee++ = '\0';
+
+		if ((regs[rd] = (uintptr_t)dtrace_json(size, json, elemlist,
+		    nelems, dest)) != 0)
+			mstate->dtms_scratch_ptr += jsonlen + 1;
+		break;
+	}
+
 	case DIF_SUBR_TOUPPER:
 	case DIF_SUBR_TOLOWER: {
 		uintptr_t s = tupregs[0].dttk_value;
@@ -4574,6 +5143,28 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
 		break;
 	}
 
+	case DIF_SUBR_STRTOLL: {
+		uintptr_t s = tupregs[0].dttk_value;
+		uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
+		int base = 10;
+
+		if (nargs > 1) {
+			if ((base = tupregs[1].dttk_value) <= 1 ||
+			    base > ('z' - 'a' + 1) + ('9' - '0' + 1)) {
+				*flags |= CPU_DTRACE_ILLOP;
+				break;
+			}
+		}
+
+		if (!dtrace_strcanload(s, size, mstate, vstate)) {
+			regs[rd] = INT64_MIN;
+			break;
+		}
+
+		regs[rd] = dtrace_strtoll((char *)s, base, size);
+		break;
+	}
+
 	case DIF_SUBR_LLTOSTR: {
 		int64_t i = (int64_t)tupregs[0].dttk_value;
 		uint64_t val, digit;
@@ -9373,7 +9964,9 @@ dtrace_difo_validate_helper(dtrace_difo_t *dp)
 			    subr == DIF_SUBR_INET_NTOA ||
 			    subr == DIF_SUBR_INET_NTOA6 ||
 			    subr == DIF_SUBR_INET_NTOP ||
+			    subr == DIF_SUBR_JSON ||
 			    subr == DIF_SUBR_LLTOSTR ||
+			    subr == DIF_SUBR_STRTOLL ||
 			    subr == DIF_SUBR_RINDEX ||
 			    subr == DIF_SUBR_STRCHR ||
 			    subr == DIF_SUBR_STRJOIN ||
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
index 2aedfeabc6ab..d7a705c65ff7 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
@@ -313,7 +313,9 @@ typedef enum dtrace_probespec {
 #define	DIF_SUBR_SX_ISEXCLUSIVE		50
 #define	DIF_SUBR_MEMSTR			51
 #define	DIF_SUBR_GETF			52
-#define	DIF_SUBR_MAX			52	/* max subroutine value */
+#define	DIF_SUBR_JSON			53
+#define	DIF_SUBR_STRTOLL		54
+#define	DIF_SUBR_MAX			54	/* max subroutine value */
 
 typedef uint32_t dif_instr_t;
 
diff --git a/sys/modules/dtrace/dtrace/Makefile b/sys/modules/dtrace/dtrace/Makefile
index ea2c1f1654aa..3a77390da8e3 100644
--- a/sys/modules/dtrace/dtrace/Makefile
+++ b/sys/modules/dtrace/dtrace/Makefile
@@ -4,6 +4,8 @@ SYSDIR?=	${.CURDIR}/../../..
 
 ARCHDIR=	${MACHINE_CPUARCH}
 
+SUNW=	${.CURDIR}/../../../../cddl/contrib/opensolaris
+
 .PATH: ${SYSDIR}/cddl/contrib/opensolaris/uts/common/dtrace
 .PATH: ${SYSDIR}/cddl/compat/opensolaris/kern
 .PATH: ${SYSDIR}/cddl/kern
@@ -20,7 +22,8 @@ SRCS=		dtrace.c \
 SRCS+=		dis_tables.c \
 		instr_size.c
 CFLAGS+=	-I${SYSDIR}/cddl/contrib/opensolaris/uts/intel \
-		-I${SYSDIR}/cddl/dev/dtrace/x86
+		-I${SYSDIR}/cddl/dev/dtrace/x86 \
+		-I${SUNW}/common/util
 .endif
 
 SRCS+=		bus_if.h device_if.h vnode_if.h