Print this page
4474 DTrace Userland CTF Support
4475 DTrace userland Keyword
4476 DTrace tests should be better citizens
4479 pid provider types
4480 dof emulation missing checks
Reviewed by: Bryan Cantrill <bryan@joyent.com>

@@ -5717,36 +5717,50 @@
                         /*FALLTHROUGH*/
                 case DIF_OP_LDX:
                         regs[rd] = dtrace_load64(regs[r1]);
                         break;
                 case DIF_OP_ULDSB:
+                        DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
                         regs[rd] = (int8_t)
                             dtrace_fuword8((void *)(uintptr_t)regs[r1]);
+                        DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
                         break;
                 case DIF_OP_ULDSH:
+                        DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
                         regs[rd] = (int16_t)
                             dtrace_fuword16((void *)(uintptr_t)regs[r1]);
+                        DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
                         break;
                 case DIF_OP_ULDSW:
+                        DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
                         regs[rd] = (int32_t)
                             dtrace_fuword32((void *)(uintptr_t)regs[r1]);
+                        DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
                         break;
                 case DIF_OP_ULDUB:
+                        DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
                         regs[rd] =
                             dtrace_fuword8((void *)(uintptr_t)regs[r1]);
+                        DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
                         break;
                 case DIF_OP_ULDUH:
+                        DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
                         regs[rd] =
                             dtrace_fuword16((void *)(uintptr_t)regs[r1]);
+                        DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
                         break;
                 case DIF_OP_ULDUW:
+                        DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
                         regs[rd] =
                             dtrace_fuword32((void *)(uintptr_t)regs[r1]);
+                        DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
                         break;
                 case DIF_OP_ULDX:
+                        DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
                         regs[rd] =
                             dtrace_fuword64((void *)(uintptr_t)regs[r1]);
+                        DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
                         break;
                 case DIF_OP_RET:
                         rval = regs[rd];
                         pc = textlen;
                         break;

@@ -6550,10 +6564,67 @@
 
 out:
         mstate->dtms_scratch_ptr = old;
 }
 
+static void
+dtrace_store_by_ref(dtrace_difo_t *dp, caddr_t tomax, size_t size,
+    size_t *valoffsp, uint64_t *valp, uint64_t end, int intuple, int dtkind)
+{
+        volatile uint16_t *flags;
+        uint64_t val = *valp;
+        size_t valoffs = *valoffsp;
+
+        flags = (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
+        ASSERT(dtkind == DIF_TF_BYREF || dtkind == DIF_TF_BYUREF);
+
+        /*
+         * If this is a string, we're going to only load until we find the zero
+         * byte -- after which we'll store zero bytes.
+         */
+        if (dp->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) {
+                char c = '\0' + 1;
+                size_t s;
+
+                for (s = 0; s < size; s++) {
+                        if (c != '\0' && dtkind == DIF_TF_BYREF) {
+                                c = dtrace_load8(val++);
+                        } else if (c != '\0' && dtkind == DIF_TF_BYUREF) {
+                                DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+                                c = dtrace_fuword8((void *)(uintptr_t)val++);
+                                DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+                                if (*flags & CPU_DTRACE_FAULT)
+                                        break;
+                        }
+
+                        DTRACE_STORE(uint8_t, tomax, valoffs++, c);
+
+                        if (c == '\0' && intuple)
+                                break;
+                }
+        } else {
+                uint8_t c;
+                while (valoffs < end) {
+                        if (dtkind == DIF_TF_BYREF) {
+                                c = dtrace_load8(val++);
+                        } else if (dtkind == DIF_TF_BYUREF) {
+                                DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+                                c = dtrace_fuword8((void *)(uintptr_t)val++);
+                                DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+                                if (*flags & CPU_DTRACE_FAULT)
+                                        break;
+                        }
+
+                        DTRACE_STORE(uint8_t, tomax,
+                            valoffs++, c);
+                }
+        }
+
+        *valp = val;
+        *valoffsp = valoffs;
+}
+
 /*
  * If you're looking for the epicenter of DTrace, you just found it.  This
  * is the function called by the provider to fire a probe -- from which all
  * subsequent probe-context DTrace activity emanates.
  */

@@ -7041,53 +7112,29 @@
 
                         default:
                                 ASSERT(0);
                         }
 
-                        if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF) {
+                        if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ||
+                            dp->dtdo_rtype.dtdt_flags & DIF_TF_BYUREF) {
                                 uintptr_t end = valoffs + size;
 
                                 if (tracememsize != 0 &&
                                     valoffs + tracememsize < end) {
                                         end = valoffs + tracememsize;
                                         tracememsize = 0;
                                 }
 
-                                if (!dtrace_vcanload((void *)(uintptr_t)val,
+                                if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF &&
+                                    !dtrace_vcanload((void *)(uintptr_t)val,
                                     &dp->dtdo_rtype, &mstate, vstate))
                                         continue;
 
-                                /*
-                                 * If this is a string, we're going to only
-                                 * load until we find the zero byte -- after
-                                 * which we'll store zero bytes.
-                                 */
-                                if (dp->dtdo_rtype.dtdt_kind ==
-                                    DIF_TYPE_STRING) {
-                                        char c = '\0' + 1;
-                                        int intuple = act->dta_intuple;
-                                        size_t s;
-
-                                        for (s = 0; s < size; s++) {
-                                                if (c != '\0')
-                                                        c = dtrace_load8(val++);
-
-                                                DTRACE_STORE(uint8_t, tomax,
-                                                    valoffs++, c);
-
-                                                if (c == '\0' && intuple)
-                                                        break;
-                                        }
-
-                                        continue;
-                                }
-
-                                while (valoffs < end) {
-                                        DTRACE_STORE(uint8_t, tomax, valoffs++,
-                                            dtrace_load8(val++));
-                                }
-
+                                dtrace_store_by_ref(dp, tomax, size, &valoffs,
+                                    &val, end, act->dta_intuple,
+                                    dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ?
+                                    DIF_TF_BYREF: DIF_TF_BYUREF);
                                 continue;
                         }
 
                         switch (size) {
                         case 0:

@@ -9201,11 +9248,11 @@
             DIF_INSTR_OP(dp->dtdo_buf[dp->dtdo_len - 1]) != DIF_OP_RET) {
                 err += efunc(dp->dtdo_len - 1,
                     "expected 'ret' as last DIF instruction\n");
         }
 
-        if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF)) {
+        if (!(dp->dtdo_rtype.dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF))) {
                 /*
                  * If we're not returning by reference, the size must be either
                  * 0 or the size of one of the base types.
                  */
                 switch (dp->dtdo_rtype.dtdt_size) {