Created
November 9, 2012 11:02
-
-
Save jclulow/4045153 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [root@ra ~]# ./json.d | |
| BOOTING AT: Fri Nov 09 2012 18:00:50 GMT+0000 (UTC) | |
| BOOTING AT: Fri Nov 09 2012 18:00:52 GMT+0000 (UTC) | |
| BOOTING AT: Fri Nov 09 2012 18:00:53 GMT+0000 (UTC) | |
| THE BOOT! 3 | |
| jacob 10 | |
| jingleheimer 10 | |
| schmidt 10 | |
| john 11 | |
| BOOTING AT: Fri Nov 09 2012 18:00:54 GMT+0000 (UTC) | |
| BOOTING AT: Fri Nov 09 2012 18:00:56 GMT+0000 (UTC) | |
| BOOTING AT: Fri Nov 09 2012 18:00:57 GMT+0000 (UTC) | |
| BOOTING AT: Fri Nov 09 2012 18:00:58 GMT+0000 (UTC) | |
| THE BOOT! 4 | |
| john 11 | |
| schmidt 11 | |
| jacob 12 | |
| jingleheimer 12 | |
| BOOTING AT: Fri Nov 09 2012 18:01:00 GMT+0000 (UTC) | |
| BOOTING AT: Fri Nov 09 2012 18:01:01 GMT+0000 (UTC) | |
| THE BOOT! 2 | |
| jacob 5 | |
| john 5 | |
| jingleheimer 6 | |
| schmidt 7 | |
| ^C |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/sbin/dtrace -Zqs | |
| jmcapp*:::awesome | |
| { | |
| this->j = copyinstr(arg0); | |
| @[json(this->j, "name")] = count(); | |
| } | |
| jmcapp*:::awesome | |
| /json(this->j, "name") == "THE BOOT!"/ | |
| { | |
| printf("BOOTING AT: %s\n", json(this->j, "date")); | |
| } | |
| tick-5s | |
| { | |
| printa(@); | |
| clear(@); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var dtrace_provider = require('dtrace-provider'); | |
| var dtp = dtrace_provider.createDTraceProvider("jmcapp"); | |
| var awesome = dtp.addProbe("awesome", "char *"); | |
| dtp.enable(); | |
| var NAMES = ['john', 'jacob', 'jingleheimer', 'schmidt']; | |
| var ii = 0; | |
| setInterval(function() { | |
| ii++; | |
| var obj = { | |
| date: Date() + '', | |
| name: ii % 13 === 0 ? 'THE BOOT!' : NAMES[ii % NAMES.length] | |
| }; | |
| awesome.fire(function(p) { | |
| return [JSON.stringify(obj)]; | |
| }); | |
| }, 100); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c | |
| index a7f8676..e6027f4 100644 | |
| --- a/usr/src/lib/libdtrace/common/dt_open.c | |
| +++ b/usr/src/lib/libdtrace/common/dt_open.c | |
| @@ -263,6 +263,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_10, | |
| + &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, | |
| diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c | |
| index 8ef84d1..8865fbd 100644 | |
| --- a/usr/src/uts/common/dtrace/dtrace.c | |
| +++ b/usr/src/uts/common/dtrace/dtrace.c | |
| @@ -464,6 +464,7 @@ dtrace_load##bits(uintptr_t addr) \ | |
| (act)->dta_difo->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) | |
| static size_t dtrace_strlen(const char *, size_t); | |
| +static int dtrace_streq(const char *, const char *, size_t); | |
| static dtrace_probe_t *dtrace_probe_lookup_id(dtrace_id_t id); | |
| static void dtrace_enabling_provide(dtrace_provider_t *); | |
| static int dtrace_enabling_match(dtrace_enabling_t *, int *); | |
| @@ -927,6 +928,25 @@ dtrace_strlen(const char *s, size_t lim) | |
| return (len); | |
| } | |
| +static int | |
| +dtrace_streq(const char *a, const char *b, size_t lim) | |
| +{ | |
| + uint_t len; | |
| + | |
| + for (len = 0; len != lim; len++) { | |
| + char aa = dtrace_load8((uintptr_t)a++); | |
| + char bb = dtrace_load8((uintptr_t)b++); | |
| + | |
| + if (aa != bb) | |
| + return (0); | |
| + | |
| + if (aa == '\0') | |
| + return (1); | |
| + } | |
| + | |
| + return (0); | |
| +} | |
| + | |
| /* | |
| * Check if an address falls within a toxic region. | |
| */ | |
| @@ -3353,6 +3373,167 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v, | |
| } | |
| } | |
| +typedef enum json_state { | |
| + JSON_REST = 1, | |
| + JSON_OBJECT, | |
| + JSON_STRING, | |
| + JSON_STRING_ESCAPE, | |
| + JSON_COLON, | |
| + JSON_COMMA, | |
| + JSON_VALUE, | |
| + JSON_COLLECT_OBJECT | |
| +} json_state_t; | |
| + | |
| +static char * | |
| +dtrace_json(uint64_t size, uintptr_t json, uintptr_t elem, char *dest) | |
| +{ | |
| + json_state_t state = JSON_REST; | |
| + uintptr_t cur = json; | |
| + uint64_t i; | |
| + uint8_t string_is_key = 0; | |
| + uint8_t collect_object = 0; | |
| + uint8_t found_key = 0; | |
| + uint8_t braces = 0; | |
| + char *dd = dest; | |
| + | |
| + for (cur = json; cur < json + size; cur++) { | |
| + char cc = dtrace_load8(cur); | |
| + if (cc == '\0' || braces > 250) | |
| + return (NULL); | |
| + | |
| + switch (state) { | |
| + case JSON_REST: | |
| + if (cc == ' ' || cc == '\t') | |
| + break; /* eat whitespace */ | |
| + | |
| + if (cc == '{') { | |
| + state = JSON_OBJECT; | |
| + break; | |
| + } | |
| + | |
| + /* XXX ERROR: unexpected object */ | |
| + return (NULL); | |
| + case JSON_OBJECT: | |
| + if (cc == ' ' || cc == '\t') | |
| + break; /* eat whitespace */ | |
| + | |
| + if (cc == '"') { | |
| + state = JSON_STRING; | |
| + string_is_key = 1; | |
| + break; | |
| + } | |
| + | |
| + /* XXX ERROR: key not found! */ | |
| + return (NULL); | |
| + case JSON_STRING: | |
| + if (cc == '\\') { | |
| + state = 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 = 0; | |
| + state = JSON_COLLECT_OBJECT; | |
| + break; | |
| + } | |
| + *dd = '\0'; | |
| + dd = dest; /* reset string buffer */ | |
| + if (string_is_key) { | |
| + if (dtrace_streq(dest, (char *)elem, | |
| + size)) | |
| + found_key = 1; | |
| + } else if (found_key) { | |
| + return (dest); | |
| + } | |
| + state = string_is_key ? JSON_COLON : | |
| + JSON_COMMA; | |
| + string_is_key = 0; | |
| + break; | |
| + } | |
| + | |
| + *dd++ = cc; | |
| + break; | |
| + case JSON_STRING_ESCAPE: | |
| + /* XXX handle \u0000 */ | |
| + /* XXX should actually *escape* things? */ | |
| + *dd++ = '\\'; | |
| + *dd++ = cc; | |
| + state = JSON_STRING; | |
| + break; | |
| + case JSON_COLON: | |
| + if (cc == ' ' || cc == '\t') | |
| + break; /* eat whitespace */ | |
| + | |
| + if (cc == ':') { | |
| + state = JSON_VALUE; | |
| + break; | |
| + } | |
| + | |
| + /* XXX ERROR: expected colon */ | |
| + return (NULL); | |
| + case JSON_COMMA: | |
| + if (cc == ' ' || cc == '\t') | |
| + break; /* eat whitespace */ | |
| + | |
| + if (cc == ',') { | |
| + state = JSON_OBJECT; | |
| + break; | |
| + } | |
| + | |
| + /*XXX ERROR: key not found or expected comma */ | |
| + return (NULL); | |
| + case JSON_VALUE: | |
| + if (cc == ' ' || cc == '\t') | |
| + break; /* eat whitespace */ | |
| + | |
| + if (cc == '{') { | |
| + *dd++ = cc; | |
| + state = JSON_COLLECT_OBJECT; | |
| + braces = 1; | |
| + break; | |
| + } | |
| + | |
| + if (cc == '"') { | |
| + state = JSON_STRING; | |
| + break; | |
| + } | |
| + | |
| + /* | |
| + * XXX ERROR: should handle types | |
| + * other than STRING or OBJECT | |
| + */ | |
| + return (NULL); | |
| + case JSON_COLLECT_OBJECT: | |
| + if (cc == '\0') | |
| + /* ERROR: unexpected end! */ | |
| + return (NULL); | |
| + *dd++ = cc; | |
| + if (cc == '"') { | |
| + collect_object = 1; | |
| + state = JSON_STRING; | |
| + } else if (cc == '}') { | |
| + if (found_key) { | |
| + *dd = '\0'; | |
| + return (dest); | |
| + } | |
| + if (--braces == 0) | |
| + state = JSON_COMMA; | |
| + } else if (cc == '{') { | |
| + braces++; | |
| + } | |
| + 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 | |
| @@ -4053,6 +4234,32 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, | |
| break; | |
| } | |
| + case DIF_SUBR_JSON: { | |
| + uintptr_t json = tupregs[0].dttk_value; | |
| + uintptr_t elem = tupregs[1].dttk_value; | |
| + uint64_t size = state->dts_options[DTRACEOPT_STRSIZE]; | |
| + char *dest = (char *)mstate->dtms_scratch_ptr; | |
| + size_t jsonlen = dtrace_strlen((char *)json, size); | |
| + size_t elemlen = dtrace_strlen((char *)elem, size); | |
| + | |
| + if (!dtrace_canload(json, jsonlen + 1, mstate, vstate) || | |
| + !dtrace_canload(elem, elemlen + 1, mstate, vstate)) { | |
| + regs[rd] = NULL; | |
| + break; | |
| + } | |
| + | |
| + if (!DTRACE_INSCRATCH(mstate, size)) { | |
| + DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH); | |
| + regs[rd] = NULL; | |
| + break; | |
| + } | |
| + | |
| + if ((regs[rd] = (uintptr_t)dtrace_json(size, json, elem, | |
| + dest)) != NULL) | |
| + mstate->dtms_scratch_ptr += size; | |
| + break; | |
| + } | |
| + | |
| case DIF_SUBR_TOUPPER: | |
| case DIF_SUBR_TOLOWER: { | |
| uintptr_t s = tupregs[0].dttk_value; | |
| diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h | |
| index e6d9e0e..3267968 100644 | |
| --- a/usr/src/uts/common/sys/dtrace.h | |
| +++ b/usr/src/uts/common/sys/dtrace.h | |
| @@ -289,8 +289,9 @@ extern "C" { | |
| #define DIF_SUBR_TOUPPER 44 | |
| #define DIF_SUBR_TOLOWER 45 | |
| #define DIF_SUBR_GETF 46 | |
| +#define DIF_SUBR_JSON 47 | |
| -#define DIF_SUBR_MAX 46 /* max subroutine value */ | |
| +#define DIF_SUBR_MAX 47 /* max subroutine value */ | |
| typedef uint32_t dif_instr_t; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment