MFV illumos
4477 DTrace should speak JSON MFC after: 2 weeks
This commit is contained in:
commit
b1f9167f94
cddl/contrib/opensolaris
cmd/dtrace/test/tst/common
aggs
json
tst.general.dtst.general.d.outtst.strsize.dtst.strsize.d.outtst.usdt.ctst.usdt.dtst.usdt.d.outusdt.d
privs
strtoll
common/util
lib/libdtrace/common
sys
@ -22,6 +22,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
|
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
#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_ntoa6((in6_addr_t *)alloca(sizeof (in6_addr_t))))
|
||||||
STRFUNC(inet_ntop(AF_INET, (void *)alloca(sizeof (ipaddr_t))))
|
STRFUNC(inet_ntop(AF_INET, (void *)alloca(sizeof (ipaddr_t))))
|
||||||
INTFUNC(getf(0))
|
INTFUNC(getf(0))
|
||||||
|
INTFUNC(strtoll("0x12EE5D5", 16))
|
||||||
|
STRFUNC(json("{\"systemtap\": false}", "systemtap"))
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
/subr == DIF_SUBR_MAX + 1/
|
/subr == DIF_SUBR_MAX + 1/
|
||||||
|
@ -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);
|
||||||
|
}
|
@ -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>|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
|{"a": 1024|
|
||||||
|
<NULL>
|
||||||
|
|
||||||
|
|{"a": 1024}|
|
||||||
|
1024
|
||||||
|
|
||||||
|
|{"a":false,"b":tru|
|
||||||
|
<NULL>
|
||||||
|
|
||||||
|
|{"a":false,"b":20}|
|
||||||
|
20
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -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!
|
||||||
|
|
@ -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);
|
||||||
|
};
|
@ -22,8 +22,8 @@
|
|||||||
#
|
#
|
||||||
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||||
# Use is subject to license terms.
|
# 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 $$
|
ppriv -s A=basic,dtrace_proc,dtrace_user $$
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ ppriv -s A=basic,dtrace_proc,dtrace_user $$
|
|||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
errorcount = 0;
|
errorcount = 0;
|
||||||
expected_errorcount = 23;
|
expected_errorcount = 27;
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN { trace(mutex_owned(&`pidlock)); }
|
BEGIN { trace(mutex_owned(&`pidlock)); }
|
||||||
@ -55,6 +55,8 @@ BEGIN { trace(strtok(`initname, "/")); }
|
|||||||
BEGIN { trace(strtok(NULL, "/")); }
|
BEGIN { trace(strtok(NULL, "/")); }
|
||||||
BEGIN { trace(strtok("foo/bar", `initname)); }
|
BEGIN { trace(strtok("foo/bar", `initname)); }
|
||||||
BEGIN { trace(strtok(NULL, `initname)); }
|
BEGIN { trace(strtok(NULL, `initname)); }
|
||||||
|
BEGIN { trace(strtoll(`initname)); }
|
||||||
|
BEGIN { trace(strtoll(`initname, 10)); }
|
||||||
BEGIN { trace(substr(`initname, 2, 3)); }
|
BEGIN { trace(substr(`initname, 2, 3)); }
|
||||||
|
|
||||||
BEGIN { trace(ddi_pathname(`top_devinfo, 1)); }
|
BEGIN { trace(ddi_pathname(`top_devinfo, 1)); }
|
||||||
@ -63,6 +65,9 @@ BEGIN { trace(strjoin("foo", `initname)); }
|
|||||||
BEGIN { trace(dirname(`initname)); }
|
BEGIN { trace(dirname(`initname)); }
|
||||||
BEGIN { trace(cleanpath(`initname)); }
|
BEGIN { trace(cleanpath(`initname)); }
|
||||||
|
|
||||||
|
BEGIN { j = "{\"/sbin/init\":\"uh oh\"}"; trace(json(j, `initname)); }
|
||||||
|
BEGIN { trace(json(`initname, "x")); }
|
||||||
|
|
||||||
ERROR {
|
ERROR {
|
||||||
errorcount++;
|
errorcount++;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
0
|
||||||
|
1
|
||||||
|
32
|
||||||
|
-32
|
||||||
|
8
|
||||||
|
42
|
||||||
|
9223372036854775807
|
||||||
|
-9223372036854775808
|
||||||
|
9223372036854775807
|
||||||
|
-9223372036854775808
|
||||||
|
-9223372036854775808
|
||||||
|
9223372036854775807
|
||||||
|
3135097598
|
||||||
|
12
|
||||||
|
2
|
||||||
|
-1819882045752187535
|
||||||
|
1985
|
||||||
|
-2012
|
||||||
|
0
|
||||||
|
|
79
cddl/contrib/opensolaris/common/util/strtolctype.h
Normal file
79
cddl/contrib/opensolaris/common/util/strtolctype.h
Normal file
@ -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 */
|
@ -123,8 +123,9 @@
|
|||||||
#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
|
#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_9_1 DT_VERSION_NUMBER(1, 9, 1)
|
||||||
#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0)
|
#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0)
|
||||||
#define DT_VERS_LATEST DT_VERS_1_10
|
#define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0)
|
||||||
#define DT_VERS_STRING "Sun D 1.10"
|
#define DT_VERS_LATEST DT_VERS_1_11
|
||||||
|
#define DT_VERS_STRING "Sun D 1.11"
|
||||||
|
|
||||||
const dt_version_t _dtrace_versions[] = {
|
const dt_version_t _dtrace_versions[] = {
|
||||||
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
|
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, /* D API 1.9 */
|
||||||
DT_VERS_1_9_1, /* D API 1.9.1 */
|
DT_VERS_1_9_1, /* D API 1.9.1 */
|
||||||
DT_VERS_1_10, /* D API 1.10 */
|
DT_VERS_1_10, /* D API 1.10 */
|
||||||
|
DT_VERS_1_11, /* D API 1.11 */
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -301,6 +303,8 @@ static const dt_ident_t _dtrace_globals[] = {
|
|||||||
DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },
|
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,
|
{ "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,
|
||||||
&dt_idops_type, "uint_t" },
|
&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,
|
{ "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
|
||||||
&dt_idops_func, "stack(...)" },
|
&dt_idops_func, "stack(...)" },
|
||||||
{ "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
|
{ "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 *)" },
|
&dt_idops_func, "string(const char *, const char *)" },
|
||||||
{ "strtok", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOK, DT_ATTR_STABCMN, DT_VERS_1_1,
|
{ "strtok", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOK, DT_ATTR_STABCMN, DT_VERS_1_1,
|
||||||
&dt_idops_func, "string(const char *, const char *)" },
|
&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,
|
{ "substr", DT_IDENT_FUNC, 0, DIF_SUBR_SUBSTR, DT_ATTR_STABCMN, DT_VERS_1_1,
|
||||||
&dt_idops_func, "string(const char *, int, [int])" },
|
&dt_idops_func, "string(const char *, int, [int])" },
|
||||||
{ "sum", DT_IDENT_AGGFUNC, 0, DTRACEAGG_SUM, DT_ATTR_STABCMN, DT_VERS_1_0,
|
{ "sum", DT_IDENT_AGGFUNC, 0, DTRACEAGG_SUM, DT_ATTR_STABCMN, DT_VERS_1_0,
|
||||||
|
@ -111,6 +111,7 @@
|
|||||||
#include <sys/zone.h>
|
#include <sys/zone.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include "strtolctype.h"
|
||||||
|
|
||||||
/* FreeBSD includes: */
|
/* FreeBSD includes: */
|
||||||
#if !defined(sun)
|
#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));
|
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.
|
* 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.
|
* 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
|
* 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;
|
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_TOUPPER:
|
||||||
case DIF_SUBR_TOLOWER: {
|
case DIF_SUBR_TOLOWER: {
|
||||||
uintptr_t s = tupregs[0].dttk_value;
|
uintptr_t s = tupregs[0].dttk_value;
|
||||||
@ -4574,6 +5143,28 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
|
|||||||
break;
|
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: {
|
case DIF_SUBR_LLTOSTR: {
|
||||||
int64_t i = (int64_t)tupregs[0].dttk_value;
|
int64_t i = (int64_t)tupregs[0].dttk_value;
|
||||||
uint64_t val, digit;
|
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_NTOA ||
|
||||||
subr == DIF_SUBR_INET_NTOA6 ||
|
subr == DIF_SUBR_INET_NTOA6 ||
|
||||||
subr == DIF_SUBR_INET_NTOP ||
|
subr == DIF_SUBR_INET_NTOP ||
|
||||||
|
subr == DIF_SUBR_JSON ||
|
||||||
subr == DIF_SUBR_LLTOSTR ||
|
subr == DIF_SUBR_LLTOSTR ||
|
||||||
|
subr == DIF_SUBR_STRTOLL ||
|
||||||
subr == DIF_SUBR_RINDEX ||
|
subr == DIF_SUBR_RINDEX ||
|
||||||
subr == DIF_SUBR_STRCHR ||
|
subr == DIF_SUBR_STRCHR ||
|
||||||
subr == DIF_SUBR_STRJOIN ||
|
subr == DIF_SUBR_STRJOIN ||
|
||||||
|
@ -313,7 +313,9 @@ typedef enum dtrace_probespec {
|
|||||||
#define DIF_SUBR_SX_ISEXCLUSIVE 50
|
#define DIF_SUBR_SX_ISEXCLUSIVE 50
|
||||||
#define DIF_SUBR_MEMSTR 51
|
#define DIF_SUBR_MEMSTR 51
|
||||||
#define DIF_SUBR_GETF 52
|
#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;
|
typedef uint32_t dif_instr_t;
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ SYSDIR?= ${.CURDIR}/../../..
|
|||||||
|
|
||||||
ARCHDIR= ${MACHINE_CPUARCH}
|
ARCHDIR= ${MACHINE_CPUARCH}
|
||||||
|
|
||||||
|
SUNW= ${.CURDIR}/../../../../cddl/contrib/opensolaris
|
||||||
|
|
||||||
.PATH: ${SYSDIR}/cddl/contrib/opensolaris/uts/common/dtrace
|
.PATH: ${SYSDIR}/cddl/contrib/opensolaris/uts/common/dtrace
|
||||||
.PATH: ${SYSDIR}/cddl/compat/opensolaris/kern
|
.PATH: ${SYSDIR}/cddl/compat/opensolaris/kern
|
||||||
.PATH: ${SYSDIR}/cddl/kern
|
.PATH: ${SYSDIR}/cddl/kern
|
||||||
@ -20,7 +22,8 @@ SRCS= dtrace.c \
|
|||||||
SRCS+= dis_tables.c \
|
SRCS+= dis_tables.c \
|
||||||
instr_size.c
|
instr_size.c
|
||||||
CFLAGS+= -I${SYSDIR}/cddl/contrib/opensolaris/uts/intel \
|
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
|
.endif
|
||||||
|
|
||||||
SRCS+= bus_if.h device_if.h vnode_if.h
|
SRCS+= bus_if.h device_if.h vnode_if.h
|
||||||
|
Loading…
x
Reference in New Issue
Block a user