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