brintos

brintos / linux-shallow public Read only

0
0
Text · 9.8 KiB · 8887cc2 Raw
300 lines · plain
1perf-dlfilter(1)2================3 4NAME5----6perf-dlfilter - Filter sample events using a dynamically loaded shared7object file8 9SYNOPSIS10--------11[verse]12'perf script' [--dlfilter file.so ] [ --dlarg arg ]...13 14DESCRIPTION15-----------16 17This option is used to process data through a custom filter provided by a18dynamically loaded shared object file. Arguments can be passed using --dlarg19and retrieved using perf_dlfilter_fns.args().20 21If 'file.so' does not contain "/", then it will be found either in the current22directory, or perf tools exec path which is ~/libexec/perf-core/dlfilters for23a local build and install (refer perf --exec-path), or the dynamic linker24paths.25 26API27---28 29The API for filtering consists of the following:30 31[source,c]32----33#include <perf/perf_dlfilter.h>34 35struct perf_dlfilter_fns perf_dlfilter_fns;36 37int start(void **data, void *ctx);38int stop(void *data, void *ctx);39int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx);40int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx);41const char *filter_description(const char **long_description);42----43 44If implemented, 'start' will be called at the beginning, before any45calls to 'filter_event' or 'filter_event_early'. Return 0 to indicate success,46or return a negative error code. '*data' can be assigned for use by other47functions. 'ctx' is needed for calls to perf_dlfilter_fns, but most48perf_dlfilter_fns are not valid when called from 'start'.49 50If implemented, 'stop' will be called at the end, after any calls to51'filter_event' or 'filter_event_early'. Return 0 to indicate success, or52return a negative error code. 'data' is set by 'start'. 'ctx' is needed53for calls to perf_dlfilter_fns, but most perf_dlfilter_fns are not valid54when called from 'stop'.55 56If implemented, 'filter_event' will be called for each sample event.57Return 0 to keep the sample event, 1 to filter it out, or return a negative58error code. 'data' is set by 'start'. 'ctx' is needed for calls to59'perf_dlfilter_fns'.60 61'filter_event_early' is the same as 'filter_event' except it is called before62internal filtering.63 64If implemented, 'filter_description' should return a one-line description65of the filter, and optionally a longer description.66 67Do not assume the 'sample' argument is valid (dereferenceable)68after 'filter_event' and 'filter_event_early' return.69 70Do not assume data referenced by pointers in struct perf_dlfilter_sample71is valid (dereferenceable) after 'filter_event' and 'filter_event_early' return.72 73The perf_dlfilter_sample structure74~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~75 76'filter_event' and 'filter_event_early' are passed a perf_dlfilter_sample77structure, which contains the following fields:78[source,c]79----80/*81 * perf sample event information (as per perf script and <linux/perf_event.h>)82 */83struct perf_dlfilter_sample {84	__u32 size; /* Size of this structure (for compatibility checking) */85	__u16 ins_lat;		/* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */86	__u16 p_stage_cyc;	/* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */87	__u64 ip;88	__s32 pid;89	__s32 tid;90	__u64 time;91	__u64 addr;92	__u64 id;93	__u64 stream_id;94	__u64 period;95	__u64 weight;		/* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */96	__u64 transaction;	/* Refer PERF_SAMPLE_TRANSACTION in <linux/perf_event.h> */97	__u64 insn_cnt;	/* For instructions-per-cycle (IPC) */98	__u64 cyc_cnt;		/* For instructions-per-cycle (IPC) */99	__s32 cpu;100	__u32 flags;		/* Refer PERF_DLFILTER_FLAG_* above */101	__u64 data_src;		/* Refer PERF_SAMPLE_DATA_SRC in <linux/perf_event.h> */102	__u64 phys_addr;	/* Refer PERF_SAMPLE_PHYS_ADDR in <linux/perf_event.h> */103	__u64 data_page_size;	/* Refer PERF_SAMPLE_DATA_PAGE_SIZE in <linux/perf_event.h> */104	__u64 code_page_size;	/* Refer PERF_SAMPLE_CODE_PAGE_SIZE in <linux/perf_event.h> */105	__u64 cgroup;		/* Refer PERF_SAMPLE_CGROUP in <linux/perf_event.h> */106	__u8  cpumode;		/* Refer CPUMODE_MASK etc in <linux/perf_event.h> */107	__u8  addr_correlates_sym; /* True => resolve_addr() can be called */108	__u16 misc;		/* Refer perf_event_header in <linux/perf_event.h> */109	__u32 raw_size;		/* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */110	const void *raw_data;	/* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */111	__u64 brstack_nr;	/* Number of brstack entries */112	const struct perf_branch_entry *brstack; /* Refer <linux/perf_event.h> */113	__u64 raw_callchain_nr;	/* Number of raw_callchain entries */114	const __u64 *raw_callchain; /* Refer <linux/perf_event.h> */115	const char *event;116	__s32 machine_pid;117	__s32 vcpu;118};119----120 121Note: 'machine_pid' and 'vcpu' are not original members, but were added together later.122'size' can be used to determine their presence at run time.123PERF_DLFILTER_HAS_MACHINE_PID will be defined if they are present at compile time.124For example:125[source,c]126----127#include <perf/perf_dlfilter.h>128#include <stddef.h>129#include <stdbool.h>130 131static inline bool have_machine_pid(const struct perf_dlfilter_sample *sample)132{133#ifdef PERF_DLFILTER_HAS_MACHINE_PID134	return sample->size >= offsetof(struct perf_dlfilter_sample, vcpu) + sizeof(sample->vcpu);135#else136	return false;137#endif138}139----140 141The perf_dlfilter_fns structure142~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~143 144The 'perf_dlfilter_fns' structure is populated with function pointers when the145file is loaded. The functions can be called by 'filter_event' or146'filter_event_early'.147 148[source,c]149----150struct perf_dlfilter_fns {151	const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);152	const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);153	char **(*args)(void *ctx, int *dlargc);154	__s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);155	const __u8 *(*insn)(void *ctx, __u32 *length);156	const char *(*srcline)(void *ctx, __u32 *line_number);157	struct perf_event_attr *(*attr)(void *ctx);158	__s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);159	void (*al_cleanup)(void *ctx, struct perf_dlfilter_al *al);160	void *(*reserved[119])(void *);161};162----163 164'resolve_ip' returns information about ip.165 166'resolve_addr' returns information about addr (if addr_correlates_sym).167 168'args' returns arguments from --dlarg options.169 170'resolve_address' provides information about 'address'. al->size must be set171before calling. Returns 0 on success, -1 otherwise. Call al_cleanup() (if present,172see below) when 'al' data is no longer needed.173 174'insn' returns instruction bytes and length.175 176'srcline' return source file name and line number.177 178'attr' returns perf_event_attr, refer <linux/perf_event.h>.179 180'object_code' reads object code and returns the number of bytes read.181 182'al_cleanup' must be called (if present, so check perf_dlfilter_fns.al_cleanup != NULL)183after resolve_address() to free any associated resources.184 185Do not assume pointers obtained via perf_dlfilter_fns are valid (dereferenceable)186after 'filter_event' and 'filter_event_early' return.187 188The perf_dlfilter_al structure189~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~190 191The 'perf_dlfilter_al' structure contains information about an address.192 193[source,c]194----195/*196 * Address location (as per perf script)197 */198struct perf_dlfilter_al {199	__u32 size; /* Size of this structure (for compatibility checking) */200	__u32 symoff;201	const char *sym;202	__u64 addr; /* Mapped address (from dso) */203	__u64 sym_start;204	__u64 sym_end;205	const char *dso;206	__u8  sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */207	__u8  is_64_bit; /* Only valid if dso is not NULL */208	__u8  is_kernel_ip; /* True if in kernel space */209	__u32 buildid_size;210	__u8 *buildid;211	/* Below members are only populated by resolve_ip() */212	__u8 filtered; /* true if this sample event will be filtered out */213	const char *comm;214	void *priv; /* Private data. Do not change */215};216----217 218Do not assume data referenced by pointers in struct perf_dlfilter_al219is valid (dereferenceable) after 'filter_event' and 'filter_event_early' return.220 221perf_dlfilter_sample flags222~~~~~~~~~~~~~~~~~~~~~~~~~~223 224The 'flags' member of 'perf_dlfilter_sample' corresponds with the flags field225of perf script. The bits of the flags are as follows:226 227[source,c]228----229/* Definitions for perf_dlfilter_sample flags */230enum {231	PERF_DLFILTER_FLAG_BRANCH	= 1ULL << 0,232	PERF_DLFILTER_FLAG_CALL		= 1ULL << 1,233	PERF_DLFILTER_FLAG_RETURN	= 1ULL << 2,234	PERF_DLFILTER_FLAG_CONDITIONAL	= 1ULL << 3,235	PERF_DLFILTER_FLAG_SYSCALLRET	= 1ULL << 4,236	PERF_DLFILTER_FLAG_ASYNC	= 1ULL << 5,237	PERF_DLFILTER_FLAG_INTERRUPT	= 1ULL << 6,238	PERF_DLFILTER_FLAG_TX_ABORT	= 1ULL << 7,239	PERF_DLFILTER_FLAG_TRACE_BEGIN	= 1ULL << 8,240	PERF_DLFILTER_FLAG_TRACE_END	= 1ULL << 9,241	PERF_DLFILTER_FLAG_IN_TX	= 1ULL << 10,242	PERF_DLFILTER_FLAG_VMENTRY	= 1ULL << 11,243	PERF_DLFILTER_FLAG_VMEXIT	= 1ULL << 12,244};245----246 247EXAMPLE248-------249 250Filter out everything except branches from "foo" to "bar":251 252[source,c]253----254#include <perf/perf_dlfilter.h>255#include <string.h>256 257struct perf_dlfilter_fns perf_dlfilter_fns;258 259int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)260{261	const struct perf_dlfilter_al *al;262	const struct perf_dlfilter_al *addr_al;263 264	if (!sample->ip || !sample->addr_correlates_sym)265		return 1;266 267	al = perf_dlfilter_fns.resolve_ip(ctx);268	if (!al || !al->sym || strcmp(al->sym, "foo"))269		return 1;270 271	addr_al = perf_dlfilter_fns.resolve_addr(ctx);272	if (!addr_al || !addr_al->sym || strcmp(addr_al->sym, "bar"))273		return 1;274 275	return 0;276}277----278 279To build the shared object, assuming perf has been installed for the local user280i.e. perf_dlfilter.h is in ~/include/perf :281 282	gcc -c -I ~/include -fpic dlfilter-example.c283	gcc -shared -o dlfilter-example.so dlfilter-example.o284 285To use the filter with perf script:286 287	perf script --dlfilter dlfilter-example.so288 289NOTES290-----291 292The dlfilter .so file will be dependent on shared libraries. If those change,293it may be necessary to rebuild the .so. Also there may be unexpected results294if the .so uses different versions of the shared libraries that perf uses.295Versions can be checked using the ldd command.296 297SEE ALSO298--------299linkperf:perf-script[1]300