Author: rpaulo
Date: Thu Jun 26 21:45:49 2014
New Revision: 267937
URL: http://svnweb.freebsd.org/changeset/base/267937

Log:
  MFV illumos
  
  4477 DTrace should speak JSON
  
  MFC after:    2 weeks

Added:
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/
     - copied from r266987, vendor/illumos/dist/cmd/dtrace/test/tst/common/json/
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/
     - copied from r266987, 
vendor/illumos/dist/cmd/dtrace/test/tst/common/strtoll/
  head/cddl/contrib/opensolaris/common/util/
     - copied from r267931, vendor/illumos/dist/common/util/
Modified:
  head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
  
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
  head/cddl/contrib/opensolaris/common/util/strtolctype.h
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
  head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
  head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
  head/sys/modules/dtrace/dtrace/Makefile
Directory Properties:
  head/cddl/contrib/opensolaris/   (props changed)
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
==============================================================================
--- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d    
Thu Jun 26 21:44:30 2014        (r267936)
+++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d    
Thu Jun 26 21:45:49 2014        (r267937)
@@ -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(siz
 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/

Modified: 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
==============================================================================
--- 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
  Thu Jun 26 21:44:30 2014        (r267936)
+++ 
head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
  Thu Jun 26 21:45:49 2014        (r267937)
@@ -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++;
 }

Modified: head/cddl/contrib/opensolaris/common/util/strtolctype.h
==============================================================================
--- vendor/illumos/dist/common/util/strtolctype.h       Thu Jun 26 19:48:59 
2014        (r267931)
+++ head/cddl/contrib/opensolaris/common/util/strtolctype.h     Thu Jun 26 
21:45:49 2014        (r267937)
@@ -44,7 +44,7 @@ extern "C" {
  * safe in probe context.
  */
 
-#if    defined(_KERNEL) || defined(_BOOT)
+#if defined(sun) &&    (defined(_KERNEL) || defined(_BOOT))
 
 #define        isalnum(ch)     (isalpha(ch) || isdigit(ch))
 #define        isalpha(ch)     (isupper(ch) || islower(ch))

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c        Thu Jun 
26 21:44:30 2014        (r267936)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c        Thu Jun 
26 21:45:49 2014        (r267937)
@@ -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,

Modified: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c        Thu Jun 
26 21:44:30 2014        (r267936)
+++ head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c        Thu Jun 
26 21:45:49 2014        (r267937)
@@ -111,6 +111,7 @@
 #include <sys/zone.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include "strtolctype.h"
 
 /* FreeBSD includes: */
 #if !defined(sun)
@@ -967,6 +968,58 @@ dtrace_vcanload(void *src, dtrace_diftyp
 }
 
 /*
+ * 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.
  */
 static int
@@ -3469,6 +3522,463 @@ dtrace_dif_variable(dtrace_mstate_t *mst
        }
 }
 
+
+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, 
                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, 
                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_
                            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 ||

Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h   Thu Jun 26 
21:44:30 2014        (r267936)
+++ head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h   Thu Jun 26 
21:45:49 2014        (r267937)
@@ -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;
 

Modified: head/sys/modules/dtrace/dtrace/Makefile
==============================================================================
--- head/sys/modules/dtrace/dtrace/Makefile     Thu Jun 26 21:44:30 2014        
(r267936)
+++ head/sys/modules/dtrace/dtrace/Makefile     Thu Jun 26 21:45:49 2014        
(r267937)
@@ -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
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to