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	__s32 machine_pid;
111	__s32 vcpu;
112};
113----
114
115Note: 'machine_pid' and 'vcpu' are not original members, but were added together later.
116'size' can be used to determine their presence at run time.
117PERF_DLFILTER_HAS_MACHINE_PID will be defined if they are present at compile time.
118For example:
119[source,c]
120----
121#include <perf/perf_dlfilter.h>
122#include <stddef.h>
123#include <stdbool.h>
124
125static inline bool have_machine_pid(const struct perf_dlfilter_sample *sample)
126{
127#ifdef PERF_DLFILTER_HAS_MACHINE_PID
128	return sample->size >= offsetof(struct perf_dlfilter_sample, vcpu) + sizeof(sample->vcpu);
129#else
130	return false;
131#endif
132}
133----
134
135The perf_dlfilter_fns structure
136~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
137
138The 'perf_dlfilter_fns' structure is populated with function pointers when the
139file is loaded. The functions can be called by 'filter_event' or
140'filter_event_early'.
141
142[source,c]
143----
144struct perf_dlfilter_fns {
145	const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);
146	const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);
147	char **(*args)(void *ctx, int *dlargc);
148	__s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);
149	const __u8 *(*insn)(void *ctx, __u32 *length);
150	const char *(*srcline)(void *ctx, __u32 *line_number);
151	struct perf_event_attr *(*attr)(void *ctx);
152	__s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);
153	void *(*reserved[120])(void *);
154};
155----
156
157'resolve_ip' returns information about ip.
158
159'resolve_addr' returns information about addr (if addr_correlates_sym).
160
161'args' returns arguments from --dlarg options.
162
163'resolve_address' provides information about 'address'. al->size must be set
164before calling. Returns 0 on success, -1 otherwise.
165
166'insn' returns instruction bytes and length.
167
168'srcline' return source file name and line number.
169
170'attr' returns perf_event_attr, refer <linux/perf_event.h>.
171
172'object_code' reads object code and returns the number of bytes read.
173
174The perf_dlfilter_al structure
175~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
176
177The 'perf_dlfilter_al' structure contains information about an address.
178
179[source,c]
180----
181/*
182 * Address location (as per perf script)
183 */
184struct perf_dlfilter_al {
185	__u32 size; /* Size of this structure (for compatibility checking) */
186	__u32 symoff;
187	const char *sym;
188	__u64 addr; /* Mapped address (from dso) */
189	__u64 sym_start;
190	__u64 sym_end;
191	const char *dso;
192	__u8  sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */
193	__u8  is_64_bit; /* Only valid if dso is not NULL */
194	__u8  is_kernel_ip; /* True if in kernel space */
195	__u32 buildid_size;
196	__u8 *buildid;
197	/* Below members are only populated by resolve_ip() */
198	__u8 filtered; /* true if this sample event will be filtered out */
199	const char *comm;
200};
201----
202
203perf_dlfilter_sample flags
204~~~~~~~~~~~~~~~~~~~~~~~~~~
205
206The 'flags' member of 'perf_dlfilter_sample' corresponds with the flags field
207of perf script. The bits of the flags are as follows:
208
209[source,c]
210----
211/* Definitions for perf_dlfilter_sample flags */
212enum {
213	PERF_DLFILTER_FLAG_BRANCH	= 1ULL << 0,
214	PERF_DLFILTER_FLAG_CALL		= 1ULL << 1,
215	PERF_DLFILTER_FLAG_RETURN	= 1ULL << 2,
216	PERF_DLFILTER_FLAG_CONDITIONAL	= 1ULL << 3,
217	PERF_DLFILTER_FLAG_SYSCALLRET	= 1ULL << 4,
218	PERF_DLFILTER_FLAG_ASYNC	= 1ULL << 5,
219	PERF_DLFILTER_FLAG_INTERRUPT	= 1ULL << 6,
220	PERF_DLFILTER_FLAG_TX_ABORT	= 1ULL << 7,
221	PERF_DLFILTER_FLAG_TRACE_BEGIN	= 1ULL << 8,
222	PERF_DLFILTER_FLAG_TRACE_END	= 1ULL << 9,
223	PERF_DLFILTER_FLAG_IN_TX	= 1ULL << 10,
224	PERF_DLFILTER_FLAG_VMENTRY	= 1ULL << 11,
225	PERF_DLFILTER_FLAG_VMEXIT	= 1ULL << 12,
226};
227----
228
229EXAMPLE
230-------
231
232Filter out everything except branches from "foo" to "bar":
233
234[source,c]
235----
236#include <perf/perf_dlfilter.h>
237#include <string.h>
238
239struct perf_dlfilter_fns perf_dlfilter_fns;
240
241int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
242{
243	const struct perf_dlfilter_al *al;
244	const struct perf_dlfilter_al *addr_al;
245
246	if (!sample->ip || !sample->addr_correlates_sym)
247		return 1;
248
249	al = perf_dlfilter_fns.resolve_ip(ctx);
250	if (!al || !al->sym || strcmp(al->sym, "foo"))
251		return 1;
252
253	addr_al = perf_dlfilter_fns.resolve_addr(ctx);
254	if (!addr_al || !addr_al->sym || strcmp(addr_al->sym, "bar"))
255		return 1;
256
257	return 0;
258}
259----
260
261To build the shared object, assuming perf has been installed for the local user
262i.e. perf_dlfilter.h is in ~/include/perf :
263
264	gcc -c -I ~/include -fpic dlfilter-example.c
265	gcc -shared -o dlfilter-example.so dlfilter-example.o
266
267To use the filter with perf script:
268
269	perf script --dlfilter dlfilter-example.so
270
271NOTES
272-----
273
274The dlfilter .so file will be dependent on shared libraries. If those change,
275it may be necessary to rebuild the .so. Also there may be unexpected results
276if the .so uses different versions of the shared libraries that perf uses.
277Versions can be checked using the ldd command.
278
279SEE ALSO
280--------
281linkperf:perf-script[1]
282