From 11fef2aa1b2adc95f0ba964c0d5aa949450d286c Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Mon, 20 May 2013 16:46:58 -0400 Subject: [PATCH] USDT implementation (phase 2). This commit contains the 2nd phase of the USDT implementation for DTrace for Linux. It provides the mechanics of fasttrap probes (enabling, firing, and disabling). It also contains various debugging statements that will be cleaned up in a future commit. They exist right now, because this commit represents a work in progress that is known to contain various bugs and loose ends. The commit for this code is provided as a "sharing of the pain" , and to ensure that others can start playing with this code and test the interaction with userspace. Signed-off-by: Kris Van Hees --- dtrace/dtrace_debug.h | 4 +- dtrace/dtrace_isa.c | 4 + dtrace/fasttrap_dev.c | 548 +++++++++++++++++- dtrace/fasttrap_impl.h | 9 +- dtrace/include/dtrace/dtrace_impl.h | 4 +- dtrace/include/uapi/linux/dtrace/fasttrap.h | 70 +++ .../uapi/linux/dtrace/fasttrap_defines.h | 41 ++ 7 files changed, 662 insertions(+), 18 deletions(-) create mode 100644 dtrace/include/uapi/linux/dtrace/fasttrap.h create mode 100644 dtrace/include/uapi/linux/dtrace/fasttrap_defines.h diff --git a/dtrace/dtrace_debug.h b/dtrace/dtrace_debug.h index a8cd96972f03..f376cfc18cbb 100644 --- a/dtrace/dtrace_debug.h +++ b/dtrace/dtrace_debug.h @@ -5,9 +5,9 @@ # undef DT_DBG_AGG # undef DT_DBG_BUF -# undef DT_DBG_DOF +# define DT_DBG_DOF # undef DT_DBG_IOCTL -# undef DT_DBG_PROBE +# define DT_DBG_PROBE #else /* CONFIG_DT_DEBUG */ diff --git a/dtrace/dtrace_isa.c b/dtrace/dtrace_isa.c index 66a95064e44d..e8105989361d 100644 --- a/dtrace/dtrace_isa.c +++ b/dtrace/dtrace_isa.c @@ -383,8 +383,12 @@ void dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, unsigned long addr = *sp; if (addr >= stack_vma->vm_start && addr < stack_vma->vm_end) { +pr_info("DEBUG: PID %5d stk[%05ld] %p = %lx -> %lx [FP?]\n", p->pid, bos - sp, sp, addr, *(unsigned long *)addr); +pr_info("DEBUG: Skipping...\n"); /* stack address - may need it for the fpstack. */ } else if (is_code_addr(addr)) { +pr_info("DEBUG: PID %5d stk[%05ld] %p = %lx\n", p->pid, bos - sp, sp, addr); +pr_info("DEBUG: Adding...\n"); *pcstack++ = addr; pcstack_limit--; } diff --git a/dtrace/fasttrap_dev.c b/dtrace/fasttrap_dev.c index 7dc08d844cd0..cc4be84af441 100644 --- a/dtrace/fasttrap_dev.c +++ b/dtrace/fasttrap_dev.c @@ -37,18 +37,21 @@ #include "fasttrap_impl.h" #define FASTTRAP_MAX_DEFAULT 250000 -static uint32_t fasttrap_max; -static atomic_t fasttrap_total; +static uint32_t fasttrap_max; +static uint64_t fasttrap_pid_count; +static atomic_t fasttrap_total; #define FASTTRAP_TPOINTS_DEFAULT_SIZE 0x4000 #define FASTTRAP_PROVIDERS_DEFAULT_SIZE 0x100 #define FASTTRAP_PROCS_DEFAULT_SIZE 0x100 #define FASTTRAP_PID_NAME "pid" +#define FASTTRAP_ENABLE_FAIL 1 +#define FASTTRAP_ENABLE_PARTIAL 2 -fasttrap_hash_t fasttrap_tpoints; -static fasttrap_hash_t fasttrap_provs; -static fasttrap_hash_t fasttrap_procs; +fasttrap_hash_t fasttrap_tpoints; +static fasttrap_hash_t fasttrap_provs; +static fasttrap_hash_t fasttrap_procs; #define FASTTRAP_PROVS_INDEX(pid, name) \ ((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask) @@ -59,8 +62,31 @@ static fasttrap_hash_t fasttrap_procs; #define CLEANUP_DEFERRED 2 DEFINE_MUTEX(fasttrap_cleanup_mtx); -static uint_t fasttrap_cleanup_state; -static uint_t fasttrap_cleanup_work; +DEFINE_MUTEX(fasttrap_count_mtx); +static uint_t fasttrap_cleanup_state; +static uint_t fasttrap_cleanup_work; + +/* + * Generation count on modifications to the global tracepoint lookup table. + */ +static volatile uint64_t fasttrap_mod_gen; + +static void fasttrap_pid_cleanup(void); + +static void fasttrap_pid_probe(fasttrap_machtp_t *mtp, struct pt_regs *regs) { + fasttrap_tracepoint_t *tp = container_of(mtp, fasttrap_tracepoint_t, + ftt_mtp); + fasttrap_id_t *id; + +pr_info("fasttrap_pid_probe(PID %d, PC %lx)\n", tp->ftt_pid, tp->ftt_pc); + for (id = tp->ftt_ids; id != NULL; id = id->fti_next) { + fasttrap_probe_t *ftp = id->fti_probe; + +pr_info(" Probe ID %d for PID %d\n", ftp->ftp_id, ftp->ftp_pid); + dtrace_probe(ftp->ftp_id, regs->di, regs->si, regs->dx, + regs->cx, regs->r8); + } +} static void fasttrap_pid_provide(void *arg, const dtrace_probedesc_t *desc) { @@ -69,15 +95,510 @@ static void fasttrap_pid_provide(void *arg, const dtrace_probedesc_t *desc) */ } -static int -fasttrap_pid_enable(void *arg, dtrace_id_t id, void *parg) +static void fasttrap_enable_callbacks(void) { - return 0; /* FIXME */ + /* + * We don't have to play the RW lock game here because we're providing + * something rather than taking something away -- we can be sure that + * no threads have tried to follow these function pointers yet. + */ + mutex_lock(&fasttrap_count_mtx); + if (fasttrap_pid_count == 0) { + ASSERT(dtrace_tracepoint_hit == NULL); + + dtrace_tracepoint_hit = &fasttrap_pid_probe; + } + + ASSERT(dtrace_tracepoint_hit == &fasttrap_pid_probe); + + fasttrap_pid_count++; + mutex_unlock(&fasttrap_count_mtx); +} + +static void fasttrap_disable_callbacks(void) +{ + ASSERT(MUTEX_HELD(&cpu_lock)); + + mutex_lock(&fasttrap_count_mtx); + ASSERT(fasttrap_pid_count > 0); + fasttrap_pid_count--; + + if (fasttrap_pid_count == 0) { + int cpu; + + for_each_present_cpu(cpu) { + cpu_core_t *cpuc = per_cpu_core(cpu); + + write_lock(&cpuc->cpu_ft_lock); + } + + dtrace_tracepoint_hit = NULL; + + for_each_present_cpu(cpu) { + cpu_core_t *cpuc = per_cpu_core(cpu); + + write_unlock(&cpuc->cpu_ft_lock); + } + } + + mutex_unlock(&fasttrap_count_mtx); +} + +/* + * his function ensures that no threads are actively using the memory + * associated with probes that were formerly live. + */ +static void fasttrap_mod_barrier(uint64_t gen) +{ + int cpu; + + if (gen < fasttrap_mod_gen) + return; + + fasttrap_mod_gen++; + + for_each_present_cpu(cpu) { + cpu_core_t *cpuc = per_cpu_core(cpu); + + mutex_lock(&cpuc->cpuc_pid_lock); + mutex_unlock(&cpuc->cpuc_pid_lock); + } +} + +static int fasttrap_tracepoint_enable(fasttrap_probe_t *probe, uint_t index) +{ + fasttrap_tracepoint_t *tp, *new_tp = NULL; + fasttrap_bucket_t *bucket; + fasttrap_id_t *id; + pid_t pid; + uintptr_t pc; + + ASSERT(index < probe->ftp_ntps); + + pid = probe->ftp_pid; + pc = probe->ftp_tps[index].fit_tp->ftt_pc; + id = &probe->ftp_tps[index].fit_id; + + ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid); + + /* + * Before we make any modifications, make sure we've imposed a barrier + * on the generation in which this probe was last modified. + */ + fasttrap_mod_barrier(probe->ftp_gen); + + bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; + + /* + * If the tracepoint has already been enabled, just add our id to the + * list of interested probes. This may be our second time through + * this path in which case we'll have constructed the tracepoint we'd + * like to install. If we can't find a match, and have an allocated + * tracepoint ready to go, enable that one now. + * + * A tracepoint whose process is defunct is also considered defunct. + */ +again: + mutex_lock(&bucket->ftb_mtx); + for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { + /* + * Note that it's safe to access the active count on the + * associated proc structure because we know that at least one + * provider (this one) will still be around throughout this + * operation. + */ + if (tp->ftt_pid != pid || tp->ftt_pc != pc || + atomic64_read(&tp->ftt_proc->ftpc_acount) == 0) + continue; + + /* + * Now that we've found a matching tracepoint, it would be + * a decent idea to confirm that the tracepoint is still + * enabled and the trap instruction hasn't been overwritten. + * Since this is a little hairy, we'll punt for now. + */ + + /* + * This can't be the first interested probe. We don't have + * to worry about another thread being in the midst of + * deleting this tracepoint (which would be the only valid + * reason for a tracepoint to have no interested probes) + * since we're holding P_PR_LOCK for this process. + */ + ASSERT(tp->ftt_ids != NULL || tp->ftt_retids != NULL); + + switch (id->fti_ptype) { + case DTFTP_ENTRY: + case DTFTP_OFFSETS: + case DTFTP_IS_ENABLED: + id->fti_next = tp->ftt_ids; + dtrace_membar_producer(); + tp->ftt_ids = id; + dtrace_membar_producer(); + break; + + case DTFTP_RETURN: + case DTFTP_POST_OFFSETS: + id->fti_next = tp->ftt_retids; + dtrace_membar_producer(); + tp->ftt_retids = id; + dtrace_membar_producer(); + break; + + default: + ASSERT(0); /* FIXME */ + } + + mutex_unlock(&bucket->ftb_mtx); + + if (new_tp != NULL) { + new_tp->ftt_ids = NULL; + new_tp->ftt_retids = NULL; + } + + return 0; + } + + /* + * If we have a good tracepoint ready to go, install it now while + * we have the lock held and no one can screw with us. + */ + if (new_tp != NULL) { + int rc = 0; + + new_tp->ftt_next = bucket->ftb_data; + dtrace_membar_producer(); + bucket->ftb_data = new_tp; + dtrace_membar_producer(); + mutex_unlock(&bucket->ftb_mtx); + + /* + * Activate the tracepoint in the ISA-specific manner. + * If this fails, we need to report the failure, but + * indicate that this tracepoint must still be disabled + * by calling fasttrap_tracepoint_disable(). + */ + if (dtrace_tracepoint_enable(pid, pc, &new_tp->ftt_mtp) != 0) + rc = FASTTRAP_ENABLE_PARTIAL; + + return rc; + } + + mutex_unlock(&bucket->ftb_mtx); + + /* + * Initialize the tracepoint that's been preallocated with the probe. + */ + new_tp = probe->ftp_tps[index].fit_tp; + + ASSERT(new_tp->ftt_pid == pid); + ASSERT(new_tp->ftt_pc == pc); + ASSERT(new_tp->ftt_proc == probe->ftp_prov->ftp_proc); + ASSERT(new_tp->ftt_ids == NULL); + ASSERT(new_tp->ftt_retids == NULL); + + switch (id->fti_ptype) { + case DTFTP_ENTRY: + case DTFTP_OFFSETS: + case DTFTP_IS_ENABLED: + id->fti_next = NULL; + new_tp->ftt_ids = id; + break; + + case DTFTP_RETURN: + case DTFTP_POST_OFFSETS: + id->fti_next = NULL; + new_tp->ftt_retids = id; + break; + + default: + ASSERT(0); + } + + goto again; +} + +static void fasttrap_tracepoint_disable(fasttrap_probe_t *probe, uint_t index) +{ + fasttrap_bucket_t *bucket; + fasttrap_provider_t *prov = probe->ftp_prov; + fasttrap_tracepoint_t **pp, *tp; + fasttrap_id_t *id, **idp = NULL; + pid_t pid; + uintptr_t pc; + + ASSERT(index < probe->ftp_ntps); + + pid = probe->ftp_pid; + pc = probe->ftp_tps[index].fit_tp->ftt_pc; + id = &probe->ftp_tps[index].fit_id; + + ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid); + + /* + * Find the tracepoint and make sure that our id is one of the + * ones registered with it. + */ + bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)]; + mutex_lock(&bucket->ftb_mtx); + for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) { + if (tp->ftt_pid == pid && tp->ftt_pc == pc && + tp->ftt_proc == prov->ftp_proc) + break; + } + + /* + * If we somehow lost this tracepoint, we are in trouble. + */ + ASSERT(tp != NULL); + + switch (id->fti_ptype) { + case DTFTP_ENTRY: + case DTFTP_OFFSETS: + case DTFTP_IS_ENABLED: + ASSERT(tp->ftt_ids != NULL); + idp = &tp->ftt_ids; + break; + + case DTFTP_RETURN: + case DTFTP_POST_OFFSETS: + ASSERT(tp->ftt_retids != NULL); + idp = &tp->ftt_retids; + break; + + default: + ASSERT(0); + } + + while ((*idp)->fti_probe != probe) { + idp = &(*idp)->fti_next; + ASSERT(*idp != NULL); + } + + id = *idp; + *idp = id->fti_next; + dtrace_membar_producer(); + + ASSERT(id->fti_probe == probe); + + /* + * If there are other registered enablings of this tracepoint, we're + * all done, but if this was the last probe assocated with this + * this tracepoint, we need to remove and free it. + */ + if (tp->ftt_ids != NULL || tp->ftt_retids != NULL) { + /* + * If the current probe's tracepoint is in use, swap it + * for an unused tracepoint. + */ + if (tp == probe->ftp_tps[index].fit_tp) { + fasttrap_probe_t *tmp_probe; + fasttrap_tracepoint_t **tmp_tp; + uint_t tmp_index; + + if (tp->ftt_ids != NULL) { + tmp_probe = tp->ftt_ids->fti_probe; + tmp_index = FASTTRAP_ID_INDEX(tp->ftt_ids); + tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp; + } else { + tmp_probe = tp->ftt_retids->fti_probe; + tmp_index = FASTTRAP_ID_INDEX(tp->ftt_retids); + tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp; + } + + ASSERT(*tmp_tp != NULL); + ASSERT(*tmp_tp != probe->ftp_tps[index].fit_tp); + ASSERT((*tmp_tp)->ftt_ids == NULL); + ASSERT((*tmp_tp)->ftt_retids == NULL); + + probe->ftp_tps[index].fit_tp = *tmp_tp; + *tmp_tp = tp; + } + + mutex_unlock(&bucket->ftb_mtx); + + /* + * Tag the modified probe with the generation in which it was + * changed. + */ + probe->ftp_gen = fasttrap_mod_gen; + return; + } + + mutex_unlock(&bucket->ftb_mtx); + + dtrace_tracepoint_disable(pid, pc, &tp->ftt_mtp); + + /* + * Remove the probe from the hash table of active tracepoints. + */ + mutex_lock(&bucket->ftb_mtx); + pp = (fasttrap_tracepoint_t **)&bucket->ftb_data; + ASSERT(*pp != NULL); + while (*pp != tp) { + pp = &(*pp)->ftt_next; + ASSERT(*pp != NULL); + } + + *pp = tp->ftt_next; + dtrace_membar_producer(); + + mutex_unlock(&bucket->ftb_mtx); + + /* + * Tag the modified probe with the generation in which it was changed. + */ + probe->ftp_gen = fasttrap_mod_gen; +} + +static int fasttrap_pid_enable(void *arg, dtrace_id_t id, void *parg) +{ + fasttrap_probe_t *probe = parg; + int i, rc; + + ASSERT(probe != NULL); + ASSERT(!probe->ftp_enabled); + ASSERT(id == probe->ftp_id); + ASSERT(MUTEX_HELD(&cpu_lock)); + + /* + * Increment the count of enabled probes on this probe's provider; + * the provider can't go away while the probe still exists. We + * must increment this even if we aren't able to properly enable + * this probe. + */ + mutex_lock(&probe->ftp_prov->ftp_mtx); + probe->ftp_prov->ftp_rcount++; + mutex_unlock(&probe->ftp_prov->ftp_mtx); + + /* + * If this probe's provider is retired (meaning it was valid in a + * previously exec'ed incarnation of this address space), bail out. The + * provider can't go away while we're in this code path. + */ + if (probe->ftp_prov->ftp_retired) + return 0; + +#ifdef FIXME + /* + * If we can't find the process, it may be that we're in the context of + * a fork in which the traced process is being born and we're copying + * USDT probes. Otherwise, the process is gone so bail. + */ + if ((p = sprlock(probe->ftp_pid)) == NULL) { + if ((curproc->p_flag & SFORKING) == 0) + return 0; + + mutex_enter(&pidlock); + p = prfind(probe->ftp_pid); + + /* + * Confirm that curproc is indeed forking the process in which + * we're trying to enable probes. + */ + ASSERT(p != NULL); + ASSERT(p->p_parent == curproc); + ASSERT(p->p_stat == SIDL); + + mutex_enter(&p->p_lock); + mutex_exit(&pidlock); + + sprlock_proc(p); + } + + ASSERT(!(p->p_flag & SVFORK)); + mutex_exit(&p->p_lock); +#endif + + /* + * We have to enable the trap entry point before any user threads have + * the chance to execute the trap instruction we're about to place + * in their process's text. + */ + fasttrap_enable_callbacks(); + + /* + * Enable all the tracepoints and add this probe's id to each + * tracepoint's list of active probes. + */ + for (i = 0; i < probe->ftp_ntps; i++) { + if ((rc = fasttrap_tracepoint_enable(probe, i)) != 0) { + /* + * If enabling the tracepoint failed completely, + * we don't have to disable it; if the failure + * was only partial we must disable it. + */ + if (rc == FASTTRAP_ENABLE_FAIL) + i--; + else + ASSERT(rc == FASTTRAP_ENABLE_PARTIAL); + + /* + * Back up and pull out all the tracepoints we've + * created so far for this probe. + */ + while (i >= 0) { + fasttrap_tracepoint_disable(probe, i); + i--; + } + +#ifdef FIXME + mutex_enter(&p->p_lock); + sprunlock(p); +#endif + + /* + * Since we're not actually enabling this probe, + * drop our reference on the trap table entry. + */ + fasttrap_disable_callbacks(); + return 0; + } + } + +#ifdef FIXME + mutex_enter(&p->p_lock); + sprunlock(p); + + probe->ftp_enabled = 1; +#endif + return 0; } static void fasttrap_pid_disable(void *arg, dtrace_id_t id, void *parg) { - /* FIXME */ + fasttrap_probe_t *probe = parg; + fasttrap_provider_t *prov = probe->ftp_prov; + int i, whack = 0; + + ASSERT(id == probe->ftp_id); + + mutex_lock(&prov->ftp_mtx); + + /* + * Disable all the associated tracepoints (for fully enabled probes). + */ + if (probe->ftp_enabled) { + for (i = 0; i < probe->ftp_ntps; i++) + fasttrap_tracepoint_disable(probe, i); + } + + ASSERT(prov->ftp_rcount > 0); + prov->ftp_rcount--; + + if ((prov->ftp_retired || prov->ftp_rcount == 0) && !prov->ftp_marked) + whack = prov->ftp_marked = 1; + + if (whack) + fasttrap_pid_cleanup(); + + if (!probe->ftp_enabled) + return; + + probe->ftp_enabled = 0; + + ASSERT(MUTEX_HELD(&cpu_lock)); + fasttrap_disable_callbacks(); } static void fasttrap_pid_getargdesc(void *arg, dtrace_id_t id, void *parg, @@ -706,6 +1227,7 @@ static void fasttrap_pid_cleanup(void) mutex_lock(&fasttrap_cleanup_mtx); fasttrap_cleanup_work = 1; fasttrap_cleanup_state = CLEANUP_SCHEDULED; +pr_info("FASTTRAP: -> Scheduling delayed cleanup...\n"); schedule_delayed_work(&fasttrap_cleanup, 3); mutex_unlock(&fasttrap_cleanup_mtx); } @@ -717,6 +1239,7 @@ void fasttrap_provider_retire(pid_t pid, const char *name, int mprov) dtrace_provider_id_t provid; ASSERT(strlen(name) < sizeof (fp->ftp_name)); +pr_info("FASTTRAP: Retiring provider '%s' for PID %d\n", name, pid); bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)]; mutex_lock(&bucket->ftb_mtx); @@ -729,6 +1252,7 @@ void fasttrap_provider_retire(pid_t pid, const char *name, int mprov) if (fp == NULL) { mutex_unlock(&bucket->ftb_mtx); +pr_info("FASTTRAP: -> Provider not found...\n"); return; } @@ -770,10 +1294,12 @@ void fasttrap_provider_retire(pid_t pid, const char *name, int mprov) * since fasttrap_provider_lookup() will ignore provider that have * been marked as retired. */ +pr_info("FASTTRAP: -> Invalidating provider...\n"); dtrace_invalidate(provid); mutex_unlock(&bucket->ftb_mtx); +pr_info("FASTTRAP: -> Calling fasttrap_pid_cleanup()...\n"); fasttrap_pid_cleanup(); } diff --git a/dtrace/fasttrap_impl.h b/dtrace/fasttrap_impl.h index e9b242463993..d34aabf2a8ec 100644 --- a/dtrace/fasttrap_impl.h +++ b/dtrace/fasttrap_impl.h @@ -1,7 +1,7 @@ #ifndef _FASTTRAP_IMPL_H_ #define _FASTTRAP_IMPL_H_ -#include +#include /* * Fasttrap Providers, Probes and Tracepoints @@ -66,8 +66,6 @@ struct fasttrap_id { fasttrap_probe_type_t fti_ptype; /* probe type */ }; -typedef unsigned long fasttrap_machtp_t; /* FIXME */ - struct fasttrap_tracepoint { fasttrap_proc_t *ftt_proc; /* associated process struct */ uintptr_t ftt_pc; /* address of tracepoint */ @@ -112,10 +110,15 @@ typedef struct fasttrap_hash { fasttrap_bucket_t *fth_table; /* array of buckets */ } fasttrap_hash_t; +extern fasttrap_hash_t fasttrap_tpoints; + #define FASTTRAP_ID_INDEX(id) \ ((fasttrap_id_tp_t *)(((char *)(id) - \ offsetof(fasttrap_id_tp_t, fit_id))) - \ &(id)->fti_probe->ftp_tps[0]) +#define FASTTRAP_TPOINTS_INDEX(pid, pc) \ + (((pc) / sizeof (fasttrap_instr_t) + (pid)) & \ + fasttrap_tpoints.fth_mask) #define FASTTRAP_OFFSET_AFRAMES 3 diff --git a/dtrace/include/dtrace/dtrace_impl.h b/dtrace/include/dtrace/dtrace_impl.h index 8aa1c6fb6c71..45902de51adb 100644 --- a/dtrace/include/dtrace/dtrace_impl.h +++ b/dtrace/include/dtrace/dtrace_impl.h @@ -846,8 +846,8 @@ extern void dtrace_cred2priv(const cred_t *, uint32_t *, uid_t *); extern void ctf_forceload(void); -#define dtrace_membar_producer() mb() -#define dtrace_membar_consumer() mb() +#define dtrace_membar_producer() wmb() +#define dtrace_membar_consumer() rmb() typedef unsigned long dtrace_icookie_t; diff --git a/dtrace/include/uapi/linux/dtrace/fasttrap.h b/dtrace/include/uapi/linux/dtrace/fasttrap.h new file mode 100644 index 000000000000..fad93dc588e3 --- /dev/null +++ b/dtrace/include/uapi/linux/dtrace/fasttrap.h @@ -0,0 +1,70 @@ +#ifndef _LINUX_DTRACE_FASTTRAP_H +#define _LINUX_DTRACE_FASTTRAP_H + +/* + * DTrace Dynamic Tracing Software: Fasttrap Provider + * + * Note: The contents of this file are private to the implementation of the + * DTrace subsystem and are subject to change at any time without notice. + */ + +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2009 -- 2013 Oracle, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include + +#define FASTTRAPIOC 0xf4 +#define FASTTRAPIOC_MAKEPROBE _IOW(FASTTRAPIOC, 1, fasttrap_probe_spec_t) +#define FASTTRAPIOC_GETINSTR _IOR(FASTTRAPIOC, 2, fasttrap_instr_query_t) + +typedef enum fasttrap_probe_type { + DTFTP_NONE = 0, + DTFTP_ENTRY, + DTFTP_RETURN, + DTFTP_OFFSETS, + DTFTP_POST_OFFSETS, + DTFTP_IS_ENABLED +} fasttrap_probe_type_t; + +typedef struct fasttrap_probe_spec { + pid_t ftps_pid; + fasttrap_probe_type_t ftps_type; + char ftps_func[DTRACE_FUNCNAMELEN]; + char ftps_mod[DTRACE_MODNAMELEN]; + uint64_t ftps_pc; + uint64_t ftps_size; + uint64_t ftps_noffs; + uint64_t ftps_offs[1]; +} fasttrap_probe_spec_t; + +typedef uint8_t fasttrap_instr_t; + +typedef struct fasttrap_instr_query { + uint64_t ftiq_pc; + pid_t ftiq_pid; + fasttrap_instr_t ftiq_instr; +} fasttrap_instr_query_t; + +#endif /* _LINUX_DTRACE_FASTTRAP_H */ diff --git a/dtrace/include/uapi/linux/dtrace/fasttrap_defines.h b/dtrace/include/uapi/linux/dtrace/fasttrap_defines.h new file mode 100644 index 000000000000..69e5329303b2 --- /dev/null +++ b/dtrace/include/uapi/linux/dtrace/fasttrap_defines.h @@ -0,0 +1,41 @@ +#ifndef _LINUX_DTRACE_FASTTRAP_DEFINES_H +#define _LINUX_DTRACE_FASTTRAP_DEFINES_H + +/* + * DTrace Dynamic Tracing Software: Fasttrap Provider + * + * Note: The contents of this file are private to the implementation of the + * DTrace subsystem and are subject to change at any time without notice. + */ + +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2009 -- 2013 Oracle, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include + +enum fasttrap_probe_type; +struct fasttrap_probe_spec; +struct fasttrap_instr_query; + +#endif /* _LINUX_DTRACE_FASTTRAP_DEFINES_H */ -- 2.50.1