if (uwrite(p, &instr, 1, tp->ftt_pc) != 0)
return (-1);
+ tp->ftt_installed = 1;
+
return (0);
}
* instruction.
*/
if (uread(p, &instr, 1, tp->ftt_pc) != 0)
- return (0);
+ goto end;
if (instr != FASTTRAP_INSTR)
- return (0);
+ goto end;
if (uwrite(p, &tp->ftt_instr[0], 1, tp->ftt_pc) != 0)
return (-1);
+end:
+ tp->ftt_installed = 0;
return (0);
}
x86_saved_state64_t *regs64;
x86_saved_state32_t *regs32;
unsigned int p_model;
+ int retire_tp = 1;
dtrace_icookie_t cookie;
}
for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
+ fasttrap_probe_t *probe = id->fti_probe;
/*
* If there's a branch that could act as a return site, we
* need to trace it, and check here if the program counter is
*/
if (tp->ftt_type != FASTTRAP_T_RET &&
tp->ftt_type != FASTTRAP_T_RET16 &&
- new_pc - id->fti_probe->ftp_faddr <
- id->fti_probe->ftp_fsize)
+ new_pc - probe->ftp_faddr < probe->ftp_fsize)
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) {
+ continue;
+ }
+ }
+ /*
+ * If we have at least one probe associated that
+ * is not a oneshot probe, don't remove the
+ * tracepoint
+ */
+ else {
+ retire_tp = 0;
+ }
/*
* Provide a hint to the stack trace functions to add the
* following pc to the top of the stack since it's missing
cookie = dtrace_interrupt_disable();
cpu_core[CPU->cpu_id].cpuc_missing_tos = pc;
if (ISSET(current_proc()->p_lflag, P_LNOATTACH)) {
- dtrace_probe(dtrace_probeid_error, 0 /* state */, id->fti_probe->ftp_id,
+ dtrace_probe(dtrace_probeid_error, 0 /* state */, probe->ftp_id,
1 /* ndx */, -1 /* offset */, DTRACEFLT_UPRIV);
} else if (p_model == DATAMODEL_LP64) {
- dtrace_probe(id->fti_probe->ftp_id,
+ dtrace_probe(probe->ftp_id,
pc - id->fti_probe->ftp_faddr,
regs64->rax, regs64->rdx, 0, 0);
} else {
- dtrace_probe(id->fti_probe->ftp_id,
+ dtrace_probe(probe->ftp_id,
pc - id->fti_probe->ftp_faddr,
regs32->eax, regs32->edx, 0, 0);
}
fasttrap_tracepoint_t *tp, tp_local;
pid_t pid;
dtrace_icookie_t cookie;
- uint_t is_enabled = 0;
+ uint_t is_enabled = 0, retire_tp = 1;
uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
if (ISSET(current_proc()->p_lflag, P_LNOATTACH)) {
dtrace_probe(dtrace_probeid_error, 0 /* state */, probe->ftp_id,
1 /* ndx */, -1 /* offset */, DTRACEFLT_UPRIV);
- } else if (id->fti_ptype == DTFTP_ENTRY) {
- /*
- * We note that this was an entry
- * probe to help ustack() find the
- * first caller.
- */
- cookie = dtrace_interrupt_disable();
- DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY);
- dtrace_probe(probe->ftp_id, s1, s2,
- s3, s4, s5);
- DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);
- dtrace_interrupt_enable(cookie);
- } else if (id->fti_ptype == DTFTP_IS_ENABLED) {
+ } 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) {
+ continue;
+ }
+ }
/*
- * Note that in this case, we don't
- * call dtrace_probe() since it's only
- * an artificial probe meant to change
- * the flow of control so that it
- * encounters the true probe.
+ * If we have at least one probe associated that
+ * is not a oneshot probe, don't remove the
+ * tracepoint
*/
- is_enabled = 1;
- } else if (probe->ftp_argmap == NULL) {
- dtrace_probe(probe->ftp_id, s0, s1,
- s2, s3, s4);
- } else {
- uint32_t t[5];
-
- fasttrap_usdt_args32(probe, regs32,
- sizeof (t) / sizeof (t[0]), t);
-
- dtrace_probe(probe->ftp_id, t[0], t[1],
- t[2], t[3], t[4]);
- }
+ else {
+ retire_tp = 0;
+ }
+ if (id->fti_ptype == DTFTP_ENTRY) {
+ /*
+ * We note that this was an entry
+ * probe to help ustack() find the
+ * first caller.
+ */
+ cookie = dtrace_interrupt_disable();
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY);
+ dtrace_probe(probe->ftp_id, s1, s2,
+ s3, s4, s5);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);
+ dtrace_interrupt_enable(cookie);
+ } else if (id->fti_ptype == DTFTP_IS_ENABLED) {
+ /*
+ * Note that in this case, we don't
+ * call dtrace_probe() since it's only
+ * an artificial probe meant to change
+ * the flow of control so that it
+ * encounters the true probe.
+ */
+ is_enabled = 1;
+ } else if (probe->ftp_argmap == NULL) {
+ dtrace_probe(probe->ftp_id, s0, s1,
+ s2, s3, s4);
+ } else {
+ uint32_t t[5];
- /* APPLE NOTE: Oneshot probes get one and only one chance... */
- if (probe->ftp_prov->ftp_provider_type == DTFTP_PROVIDER_ONESHOT) {
- fasttrap_tracepoint_remove(p, tp);
+ fasttrap_usdt_args32(probe, regs32,
+ sizeof (t) / sizeof (t[0]), t);
+
+ dtrace_probe(probe->ftp_id, t[0], t[1],
+ t[2], t[3], t[4]);
+ }
}
}
+ if (retire_tp) {
+ fasttrap_tracepoint_retire(p, tp);
+ }
}
/*
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;
*/
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;
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;
pid_t pid;
dtrace_icookie_t cookie;
uint_t is_enabled = 0;
+ int retire_tp = 1;
uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread());
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) {
+ continue;
+ }
+ }
+ /*
+ * If we have at least probe associated that
+ * is not a oneshot probe, don't remove the
+ * tracepoint
+ */
+ else {
+ retire_tp = 0;
+ }
if (ISSET(current_proc()->p_lflag, P_LNOATTACH)) {
dtrace_probe(dtrace_probeid_error, 0 /* state */, probe->ftp_id,
1 /* ndx */, -1 /* offset */, DTRACEFLT_UPRIV);
t[2], t[3], t[4]);
}
- /* APPLE NOTE: Oneshot probes get one and only one chance... */
- if (probe->ftp_prov->ftp_provider_type == DTFTP_PROVIDER_ONESHOT) {
- fasttrap_tracepoint_remove(p, tp);
- }
+ }
+ if (retire_tp) {
+ fasttrap_tracepoint_retire(p, tp);
}
}
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;
*/
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;
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;