1perf-dlfilter(1)
2================
3
4NAME
5----
6perf-dlfilter - Filter sample events using a dynamically loaded shared
7object file
8
9SYNOPSIS
10--------
11[verse]
12'perf script' [--dlfilter file.so ] [ --dlarg arg ]...
13
14DESCRIPTION
15-----------
16
17This option is used to process data through a custom filter provided by a
18dynamically loaded shared object file. Arguments can be passed using --dlarg
19and retrieved using perf_dlfilter_fns.args().
20
21If 'file.so' does not contain "/", then it will be found either in the current
22directory, or perf tools exec path which is ~/libexec/perf-core/dlfilters for
23a local build and install (refer perf --exec-path), or the dynamic linker
24paths.
25
26API
27---
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 any
45calls 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 other
47functions. 'ctx' is needed for calls to perf_dlfilter_fns, but most
48perf_dlfilter_fns are not valid when called from 'start'.
49
50If implemented, 'stop' will be called at the end, after any calls to
51'filter_event' or 'filter_event_early'. Return 0 to indicate success, or
52return a negative error code. 'data' is set by 'start'. 'ctx' is needed
53for calls to perf_dlfilter_fns, but most perf_dlfilter_fns are not valid
54when 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 negative
58error code. 'data' is set by 'start'. 'ctx' is needed for calls to
59'perf_dlfilter_fns'.
60
61'filter_event_early' is the same as 'filter_event' except it is called before
62internal filtering.
63
64If implemented, 'filter_description' should return a one-line description
65of the filter, and optionally a longer description.
66
67The perf_dlfilter_sample structure
68~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69
70'filter_event' and 'filter_event_early' are passed a perf_dlfilter_sample
71structure, which contains the following fields:
72[source,c]
73----
74/*
75 * perf sample event information (as per perf script and <linux/perf_event.h>)
76 */
77struct perf_dlfilter_sample {
78	__u32 size; /* Size of this structure (for compatibility checking) */
79	__u16 ins_lat;		/* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
80	__u16 p_stage_cyc;	/* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
81	__u64 ip;
82	__s32 pid;
83	__s32 tid;
84	__u64 time;
85	__u64 addr;
86	__u64 id;
87	__u64 stream_id;
88	__u64 period;
89	__u64 weight;		/* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
90	__u64 transaction;	/* Refer PERF_SAMPLE_TRANSACTION in <linux/perf_event.h> */
91	__u64 insn_cnt;	/* For instructions-per-cycle (IPC) */
92	__u64 cyc_cnt;		/* For instructions-per-cycle (IPC) */
93	__s32 cpu;
94	__u32 flags;		/* Refer PERF_DLFILTER_FLAG_* above */
95	__u64 data_src;		/* Refer PERF_SAMPLE_DATA_SRC in <linux/perf_event.h> */
96	__u64 phys_addr;	/* Refer PERF_SAMPLE_PHYS_ADDR in <linux/perf_event.h> */
97	__u64 data_page_size;	/* Refer PERF_SAMPLE_DATA_PAGE_SIZE in <linux/perf_event.h> */
98	__u64 code_page_size;	/* Refer PERF_SAMPLE_CODE_PAGE_SIZE in <linux/perf_event.h> */
99	__u64 cgroup;		/* Refer PERF_SAMPLE_CGROUP in <linux/perf_event.h> */
100	__u8  cpumode;		/* Refer CPUMODE_MASK etc in <linux/perf_event.h> */
101	__u8  addr_correlates_sym; /* True => resolve_addr() can be called */
102	__u16 misc;		/* Refer perf_event_header in <linux/perf_event.h> */
103	__u32 raw_size;		/* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
104	const void *raw_data;	/* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
105	__u64 brstack_nr;	/* Number of brstack entries */
106	const struct perf_branch_entry *brstack; /* Refer <linux/perf_event.h> */
107	__u64 raw_callchain_nr;	/* Number of raw_callchain entries */
108	const __u64 *raw_callchain; /* Refer <linux/perf_event.h> */
109	const char *event;
110};
111----
112
113The perf_dlfilter_fns structure
114~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115
116The 'perf_dlfilter_fns' structure is populated with function pointers when the
117file is loaded. The functions can be called by 'filter_event' or
118'filter_event_early'.
119
120[source,c]
121----
122struct perf_dlfilter_fns {
123	const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);
124	const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);
125	char **(*args)(void *ctx, int *dlargc);
126	__s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);
127	const __u8 *(*insn)(void *ctx, __u32 *length);
128	const char *(*srcline)(void *ctx, __u32 *line_number);
129	struct perf_event_attr *(*attr)(void *ctx);
130	__s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);
131	void *(*reserved[120])(void *);
132};
133----
134
135'resolve_ip' returns information about ip.
136
137'resolve_addr' returns information about addr (if addr_correlates_sym).
138
139'args' returns arguments from --dlarg options.
140
141'resolve_address' provides information about 'address'. al->size must be set
142before calling. Returns 0 on success, -1 otherwise.
143
144'insn' returns instruction bytes and length.
145
146'srcline' return source file name and line number.
147
148'attr' returns perf_event_attr, refer <linux/perf_event.h>.
149
150'object_code' reads object code and returns the number of bytes read.
151
152The perf_dlfilter_al structure
153~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154
155The 'perf_dlfilter_al' structure contains information about an address.
156
157[source,c]
158----
159/*
160 * Address location (as per perf script)
161 */
162struct perf_dlfilter_al {
163	__u32 size; /* Size of this structure (for compatibility checking) */
164	__u32 symoff;
165	const char *sym;
166	__u64 addr; /* Mapped address (from dso) */
167	__u64 sym_start;
168	__u64 sym_end;
169	const char *dso;
170	__u8  sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */
171	__u8  is_64_bit; /* Only valid if dso is not NULL */
172	__u8  is_kernel_ip; /* True if in kernel space */
173	__u32 buildid_size;
174	__u8 *buildid;
175	/* Below members are only populated by resolve_ip() */
176	__u8 filtered; /* true if this sample event will be filtered out */
177	const char *comm;
178};
179----
180
181perf_dlfilter_sample flags
182~~~~~~~~~~~~~~~~~~~~~~~~~~
183
184The 'flags' member of 'perf_dlfilter_sample' corresponds with the flags field
185of perf script. The bits of the flags are as follows:
186
187[source,c]
188----
189/* Definitions for perf_dlfilter_sample flags */
190enum {
191	PERF_DLFILTER_FLAG_BRANCH	= 1ULL << 0,
192	PERF_DLFILTER_FLAG_CALL		= 1ULL << 1,
193	PERF_DLFILTER_FLAG_RETURN	= 1ULL << 2,
194	PERF_DLFILTER_FLAG_CONDITIONAL	= 1ULL << 3,
195	PERF_DLFILTER_FLAG_SYSCALLRET	= 1ULL << 4,
196	PERF_DLFILTER_FLAG_ASYNC	= 1ULL << 5,
197	PERF_DLFILTER_FLAG_INTERRUPT	= 1ULL << 6,
198	PERF_DLFILTER_FLAG_TX_ABORT	= 1ULL << 7,
199	PERF_DLFILTER_FLAG_TRACE_BEGIN	= 1ULL << 8,
200	PERF_DLFILTER_FLAG_TRACE_END	= 1ULL << 9,
201	PERF_DLFILTER_FLAG_IN_TX	= 1ULL << 10,
202	PERF_DLFILTER_FLAG_VMENTRY	= 1ULL << 11,
203	PERF_DLFILTER_FLAG_VMEXIT	= 1ULL << 12,
204};
205----
206
207EXAMPLE
208-------
209
210Filter out everything except branches from "foo" to "bar":
211
212[source,c]
213----
214#include <perf/perf_dlfilter.h>
215#include <string.h>
216
217struct perf_dlfilter_fns perf_dlfilter_fns;
218
219int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
220{
221	const struct perf_dlfilter_al *al;
222	const struct perf_dlfilter_al *addr_al;
223
224	if (!sample->ip || !sample->addr_correlates_sym)
225		return 1;
226
227	al = perf_dlfilter_fns.resolve_ip(ctx);
228	if (!al || !al->sym || strcmp(al->sym, "foo"))
229		return 1;
230
231	addr_al = perf_dlfilter_fns.resolve_addr(ctx);
232	if (!addr_al || !addr_al->sym || strcmp(addr_al->sym, "bar"))
233		return 1;
234
235	return 0;
236}
237----
238
239To build the shared object, assuming perf has been installed for the local user
240i.e. perf_dlfilter.h is in ~/include/perf :
241
242	gcc -c -I ~/include -fpic dlfilter-example.c
243	gcc -shared -o dlfilter-example.so dlfilter-example.o
244
245To use the filter with perf script:
246
247	perf script --dlfilter dlfilter-example.so
248
249NOTES
250-----
251
252The dlfilter .so file will be dependent on shared libraries. If those change,
253it may be necessary to rebuild the .so. Also there may be unexpected results
254if the .so uses different versions of the shared libraries that perf uses.
255Versions can be checked using the ldd command.
256
257SEE ALSO
258--------
259linkperf:perf-script[1]
260