]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/i386/fasttrap_isa.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / dev / i386 / fasttrap_isa.c
index a70039322d766d039226d1eead899b8ec66ddd24..3577b3109143e5271e833dfe2c3ff823aa9fbfe4 100644 (file)
  * Use is subject to license terms.
  */
 
-/*
- * #pragma ident       "@(#)fasttrap_isa.c     1.27    08/04/09 SMI"
- */
-
-#ifdef KERNEL
-#ifndef _KERNEL
-#define _KERNEL /* Solaris vs. Darwin */
-#endif
-#endif
-
 #include <sys/fasttrap_isa.h>
 #include <sys/fasttrap_impl.h>
 #include <sys/dtrace.h>
@@ -235,7 +225,7 @@ fasttrap_anarg(x86_saved_state_t *regs, int function_entry, int argno)
 
        if (p_model == DATAMODEL_LP64) {
                user_addr_t stack;
-               
+
                /*
                 * In 64-bit mode, the first six arguments are stored in
                 * registers.
@@ -323,22 +313,22 @@ fasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, user_addr_t pc,
                switch (instr[start]) {
                case FASTTRAP_PREFIX_SS:
                        seg++;
-                       /*FALLTHRU*/
+                       OS_FALLTHROUGH;
                case FASTTRAP_PREFIX_GS:
                        seg++;
-                       /*FALLTHRU*/
+                       OS_FALLTHROUGH;
                case FASTTRAP_PREFIX_FS:
                        seg++;
-                       /*FALLTHRU*/
+                       OS_FALLTHROUGH;
                case FASTTRAP_PREFIX_ES:
                        seg++;
-                       /*FALLTHRU*/
+                       OS_FALLTHROUGH;
                case FASTTRAP_PREFIX_DS:
                        seg++;
-                       /*FALLTHRU*/
+                       OS_FALLTHROUGH;
                case FASTTRAP_PREFIX_CS:
                        seg++;
-                       /*FALLTHRU*/
+                       OS_FALLTHROUGH;
                case FASTTRAP_PREFIX_OPERAND:
                case FASTTRAP_PREFIX_ADDRESS:
                case FASTTRAP_PREFIX_LOCK:
@@ -725,8 +715,8 @@ fasttrap_return_common(x86_saved_state_t *regs, user_addr_t pc, pid_t pid,
                        continue;
 
                if (probe->ftp_prov->ftp_provider_type == DTFTP_PROVIDER_ONESHOT) {
-                       uint8_t already_triggered = atomic_or_8(&probe->ftp_triggered, 1);
-                       if (already_triggered) {
+                       if (os_atomic_xchg(&probe->ftp_triggered, 1, relaxed)) {
+                               /* already triggered */
                                continue;
                        }
                }
@@ -767,14 +757,14 @@ fasttrap_return_common(x86_saved_state_t *regs, user_addr_t pc, pid_t pid,
 
 static void
 fasttrap_sigsegv(proc_t *p, uthread_t t, user_addr_t addr)
-{      
+{
        proc_lock(p);
 
        /* Set fault address and mark signal */
        t->uu_code = addr;
        t->uu_siglist |= sigmask(SIGSEGV);
 
-       /* 
+       /*
          * XXX These two line may be redundant; if not, then we need
         * XXX to potentially set the data address in the machine
         * XXX specific thread state structure to indicate the address.
@@ -1041,10 +1031,10 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
 
        if (tp->ftt_ids != NULL) {
                fasttrap_id_t *id;
-               
+
                uint32_t s0, s1, s2, s3, s4, s5;
                uint32_t *stack = (uint32_t *)(uintptr_t)(regs32->uesp);
-               
+
                /*
                 * In 32-bit mode, all arguments are passed on the
                 * stack. If this is a function entry probe, we need
@@ -1058,17 +1048,17 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                fasttrap_fuword32_noerr((user_addr_t)(unsigned long)&stack[3], &s3);
                fasttrap_fuword32_noerr((user_addr_t)(unsigned long)&stack[4], &s4);
                fasttrap_fuword32_noerr((user_addr_t)(unsigned long)&stack[5], &s5);
-               
+
                for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
                        fasttrap_probe_t *probe = id->fti_probe;
-                       
+
                        if (ISSET(current_proc()->p_lflag, P_LNOATTACH)) {
-                               dtrace_probe(dtrace_probeid_error, 0 /* state */, probe->ftp_id, 
+                               dtrace_probe(dtrace_probeid_error, 0 /* state */, probe->ftp_id,
                                             1 /* ndx */, -1 /* offset */, DTRACEFLT_UPRIV);
                        } else {
                                if (probe->ftp_prov->ftp_provider_type == DTFTP_PROVIDER_ONESHOT) {
-                                       uint8_t already_triggered = atomic_or_8(&probe->ftp_triggered, 1);
-                                       if (already_triggered) {
+                                       if (os_atomic_xchg(&probe->ftp_triggered, 1, relaxed)) {
+                                               /* already triggered */
                                                continue;
                                        }
                                }
@@ -1182,10 +1172,10 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                                new_pc = pc;
                                break;
                        }
-                       
+
                        if (tp->ftt_type == FASTTRAP_T_RET16)
                                addr += tp->ftt_dest;
-                       
+
                        regs32->uesp = addr;
                        new_pc = dst;
                        break;
@@ -1194,7 +1184,7 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                case FASTTRAP_T_JCC:
                {
                        uint_t taken;
-                       
+
                        switch (tp->ftt_code) {
                                case FASTTRAP_JO:
                                        taken = (regs32->efl & FASTTRAP_EFLAGS_OF) != 0;
@@ -1255,7 +1245,7 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                                default:
                                        taken = FALSE;
                        }
-                       
+
                        if (taken)
                                new_pc = tp->ftt_dest;
                        else
@@ -1283,7 +1273,7 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                                default:
                                        taken = FALSE;
                        }
-                       
+
                        if (taken)
                                new_pc = tp->ftt_dest;
                        else
@@ -1294,7 +1284,7 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                case FASTTRAP_T_JCXZ:
                {
                        greg_t cx = regs32->ecx;
-                       
+
                        if (cx == 0)
                                new_pc = tp->ftt_dest;
                        else
@@ -1306,18 +1296,18 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                {
                        user_addr_t addr = regs32->uesp - sizeof (uint32_t);
                        int ret = fasttrap_suword32(addr, (uint32_t)regs32->ebp);
-                       
+
                        if (ret == -1) {
                                fasttrap_sigsegv(p, uthread, addr);
                                new_pc = pc;
                                break;
                        }
-                       
+
                        regs32->uesp = addr;
                        new_pc = pc + tp->ftt_size;
                        break;
                }
-               
+
                case FASTTRAP_T_NOP:
                        new_pc = pc + tp->ftt_size;
                        break;
@@ -1334,7 +1324,7 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                                if (tp->ftt_index != FASTTRAP_NOREG)
                                        addr += fasttrap_getreg(regs, tp->ftt_index) <<
                                                tp->ftt_scale;
-                               
+
                                if (tp->ftt_code == 1) {
                                        /*
                                         * If there's a segment prefix for this
@@ -1348,7 +1338,7 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                                                new_pc = pc;
                                                break;
                                        }
-                                       
+
                                        uint32_t value32;
                                        addr = (user_addr_t)(uint32_t)addr;
                                        if (fasttrap_fuword32(addr, &value32) == -1) {
@@ -1371,20 +1361,20 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                        if (tp->ftt_type == FASTTRAP_T_CALL) {
                                user_addr_t addr = regs32->uesp - sizeof (uint32_t);
                                int ret = fasttrap_suword32(addr, (uint32_t)(pc + tp->ftt_size));
-                               
+
                                if (ret == -1) {
                                        fasttrap_sigsegv(p, uthread, addr);
                                        new_pc = pc;
                                        break;
                                }
-                               
+
                                regs32->uesp = addr;
                        }
                        break;
 
                case FASTTRAP_T_COMMON:
                {
-                       user_addr_t addr;
+                       user_addr_t addr, write_addr;
                        uint8_t scratch[2 * FASTTRAP_MAX_INSTR_SIZE + 7];
                        uint_t i = 0;
 
@@ -1428,8 +1418,9 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                         */
 
                        addr = uthread->t_dtrace_scratch->addr;
+                       write_addr = uthread->t_dtrace_scratch->write_addr;
 
-                       if (addr == 0LL) {
+                       if (addr == 0LL || write_addr == 0LL) {
                                fasttrap_sigtrap(p, uthread, pc); // Should be killing target proc
                                new_pc = pc;
                                break;
@@ -1455,15 +1446,15 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                        i += tp->ftt_size;
                        scratch[i++] = FASTTRAP_INT;
                        scratch[i++] = T_DTRACE_RET;
-                       
+
                        ASSERT(i <= sizeof (scratch));
 
-                       if (fasttrap_copyout(scratch, addr, i)) {
+                       if (fasttrap_copyout(scratch, write_addr, i)) {
                                fasttrap_sigtrap(p, uthread, pc);
                                new_pc = pc;
                                break;
                        }
-                       
+
                        if (tp->ftt_retids != NULL) {
                                uthread->t_dtrace_step = 1;
                                uthread->t_dtrace_ret = 1;
@@ -1471,17 +1462,17 @@ fasttrap_pid_probe32(x86_saved_state_t *regs)
                        } else {
                                new_pc = uthread->t_dtrace_scrpc;
                        }
-                       
+
                        uthread->t_dtrace_pc = pc;
                        uthread->t_dtrace_npc = pc + tp->ftt_size;
                        uthread->t_dtrace_on = 1;
                        break;
                }
-               
+
                default:
                        panic("fasttrap: mishandled an instruction");
        }
-       
+
 done:
        /*
         * APPLE NOTE:
@@ -1618,10 +1609,10 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
 
                for (id = tp->ftt_ids; id != NULL; id = id->fti_next) {
                        fasttrap_probe_t *probe = id->fti_probe;
-                       
+
                        if (probe->ftp_prov->ftp_provider_type == DTFTP_PROVIDER_ONESHOT) {
-                               uint8_t already_triggered = atomic_or_8(&probe->ftp_triggered, 1);
-                               if (already_triggered) {
+                               if (os_atomic_xchg(&probe->ftp_triggered, 1, relaxed)) {
+                                       /* already triggered */
                                        continue;
                                }
                        }
@@ -1634,7 +1625,7 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                                retire_tp = 0;
                        }
                        if (ISSET(current_proc()->p_lflag, P_LNOATTACH)) {
-                               dtrace_probe(dtrace_probeid_error, 0 /* state */, probe->ftp_id, 
+                               dtrace_probe(dtrace_probeid_error, 0 /* state */, probe->ftp_id,
                                             1 /* ndx */, -1 /* offset */, DTRACEFLT_UPRIV);
                        } else if (id->fti_ptype == DTFTP_ENTRY) {
                                /*
@@ -1664,10 +1655,10 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                                             regs64->r8);
                        } else {
                                uint64_t t[5];
-                               
+
                                fasttrap_usdt_args64(probe, regs64,
                                                     sizeof (t) / sizeof (t[0]), t);
-                               
+
                                dtrace_probe(probe->ftp_id, t[0], t[1],
                                             t[2], t[3], t[4]);
                        }
@@ -1724,7 +1715,7 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                        user_addr_t dst;
                        user_addr_t addr;
                        int ret;
-                       
+
                        /*
                         * We have to emulate _every_ facet of the behavior of a ret
                         * instruction including what happens if the load from %esp
@@ -1732,25 +1723,25 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                         */
                        ret = fasttrap_fuword64((user_addr_t)regs64->isf.rsp, &dst);
                        addr = regs64->isf.rsp + sizeof (uint64_t);
-                       
+
                        if (ret == -1) {
                                fasttrap_sigsegv(p, uthread, (user_addr_t)regs64->isf.rsp);
                                new_pc = pc;
                                break;
                        }
-                       
+
                        if (tp->ftt_type == FASTTRAP_T_RET16)
                                addr += tp->ftt_dest;
-                       
+
                        regs64->isf.rsp = addr;
                        new_pc = dst;
                        break;
                }
-               
+
                case FASTTRAP_T_JCC:
                {
                        uint_t taken;
-                       
+
                        switch (tp->ftt_code) {
                                case FASTTRAP_JO:
                                        taken = (regs64->isf.rflags & FASTTRAP_EFLAGS_OF) != 0;
@@ -1811,7 +1802,7 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                                default:
                                        taken = FALSE;
                        }
-                       
+
                        if (taken)
                                new_pc = tp->ftt_dest;
                        else
@@ -1823,7 +1814,7 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                {
                        uint_t taken;
                        uint64_t cx = regs64->rcx--;
-                       
+
                        switch (tp->ftt_code) {
                                case FASTTRAP_LOOPNZ:
                                        taken = (regs64->isf.rflags & FASTTRAP_EFLAGS_ZF) == 0 &&
@@ -1839,14 +1830,14 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                                default:
                                        taken = FALSE;
                        }
-                       
+
                        if (taken)
                                new_pc = tp->ftt_dest;
                        else
                                new_pc = pc + tp->ftt_size;
                        break;
                }
-               
+
                case FASTTRAP_T_JCXZ:
                {
                        uint64_t cx = regs64->rcx;
@@ -1862,18 +1853,18 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                {
                        user_addr_t addr = regs64->isf.rsp - sizeof (uint64_t);
                        int ret = fasttrap_suword64(addr, (uint64_t)regs64->rbp);
-                       
+
                        if (ret == -1) {
                                fasttrap_sigsegv(p, uthread, addr);
                                new_pc = pc;
                                break;
                        }
-                       
+
                        regs64->isf.rsp = addr;
                        new_pc = pc + tp->ftt_size;
                        break;
                }
-               
+
                case FASTTRAP_T_NOP:
                        new_pc = pc + tp->ftt_size;
                        break;
@@ -1884,13 +1875,13 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                                new_pc = tp->ftt_dest;
                        } else {
                                user_addr_t value, addr = tp->ftt_dest;
-                               
+
                                if (tp->ftt_base != FASTTRAP_NOREG)
                                        addr += fasttrap_getreg(regs, tp->ftt_base);
                                if (tp->ftt_index != FASTTRAP_NOREG)
                                        addr += fasttrap_getreg(regs, tp->ftt_index) <<
                                                tp->ftt_scale;
-                               
+
                                if (tp->ftt_code == 1) {
                                        /*
                                         * If there's a segment prefix for this
@@ -1904,7 +1895,7 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                                                new_pc = pc;
                                                break;
                                        }
-                                       
+
                                        if (fasttrap_fuword64(addr, &value) == -1) {
                                                fasttrap_sigsegv(p, uthread, addr);
                                                new_pc = pc;
@@ -1925,23 +1916,23 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                        if (tp->ftt_type == FASTTRAP_T_CALL) {
                                user_addr_t addr = regs64->isf.rsp - sizeof (uint64_t);
                                int ret = fasttrap_suword64(addr, pc + tp->ftt_size);
-                               
+
                                if (ret == -1) {
                                        fasttrap_sigsegv(p, uthread, addr);
                                        new_pc = pc;
                                        break;
                                }
-                               
+
                                regs64->isf.rsp = addr;
                        }
                        break;
 
                case FASTTRAP_T_COMMON:
                {
-                       user_addr_t addr;
+                       user_addr_t addr, write_addr;
                        uint8_t scratch[2 * FASTTRAP_MAX_INSTR_SIZE + 22];
                        uint_t i = 0;
-                       
+
                        /*
                         * Generic Instruction Tracing
                         * ---------------------------
@@ -2026,8 +2017,9 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                         */
 
                        addr = uthread->t_dtrace_scratch->addr;
+                       write_addr = uthread->t_dtrace_scratch->write_addr;
 
-                       if (addr == 0LL) {
+                       if (addr == 0LL || write_addr == 0LL) {
                                fasttrap_sigtrap(p, uthread, pc); // Should be killing target proc
                                new_pc = pc;
                                break;
@@ -2041,10 +2033,10 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
 
                        if (tp->ftt_ripmode != 0) {
                                uint64_t* reg;
-                               
+
                                ASSERT(tp->ftt_ripmode &
                                       (FASTTRAP_RIP_1 | FASTTRAP_RIP_2));
-                               
+
                                /*
                                 * If this was a %rip-relative instruction, we change
                                 * it to be either a %rax- or %rcx-relative
@@ -2058,12 +2050,12 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                                        scratch[i++] = FASTTRAP_REX(1, 0, 0, 1);
                                else
                                        scratch[i++] = FASTTRAP_REX(1, 0, 0, 0);
-                               
+
                                if (tp->ftt_ripmode & FASTTRAP_RIP_1)
                                        scratch[i++] = FASTTRAP_MOV_EAX;
                                else
                                        scratch[i++] = FASTTRAP_MOV_ECX;
-                               
+
                                switch (tp->ftt_ripmode) {
                                        case FASTTRAP_RIP_1:
                                                reg = &regs64->rax;
@@ -2085,7 +2077,7 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                                                reg = NULL;
                                                panic("unhandled ripmode in fasttrap_pid_probe64");
                                }
-                               
+
                                /* LINTED - alignment */
                                *(uint64_t *)&scratch[i] = *reg;
                                uthread->t_dtrace_regv = *reg;
@@ -2117,7 +2109,7 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
 
                        ASSERT(i <= sizeof (scratch));
 
-                       if (fasttrap_copyout(scratch, addr, i)) {
+                       if (fasttrap_copyout(scratch, write_addr, i)) {
                                fasttrap_sigtrap(p, uthread, pc);
                                new_pc = pc;
                                break;
@@ -2130,17 +2122,17 @@ fasttrap_pid_probe64(x86_saved_state_t *regs)
                        } else {
                                new_pc = uthread->t_dtrace_scrpc;
                        }
-                       
+
                        uthread->t_dtrace_pc = pc;
                        uthread->t_dtrace_npc = pc + tp->ftt_size;
                        uthread->t_dtrace_on = 1;
                        break;
                }
-               
+
                default:
                        panic("fasttrap: mishandled an instruction");
        }
-       
+
 done:
        /*
         * APPLE NOTE: