1PERF-DLFILTER(1)                  perf Manual                 PERF-DLFILTER(1)
2
3
4

NAME

6       perf-dlfilter - Filter sample events using a dynamically loaded shared
7       object file
8

SYNOPSIS

10       perf script [--dlfilter file.so ] [ --dlarg arg ]...
11

DESCRIPTION

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

API

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       Do not assume the sample argument is valid (dereferenceable) after
59       filter_event and filter_event_early return.
60
61       Do not assume data referenced by pointers in struct
62       perf_dlfilter_sample is valid (dereferenceable) after filter_event and
63       filter_event_early return.
64
65   The perf_dlfilter_sample structure
66       filter_event and filter_event_early are passed a perf_dlfilter_sample
67       structure, which contains the following fields:
68
69           /*
70            * perf sample event information (as per perf script and <linux/perf_event.h>)
71            */
72           struct perf_dlfilter_sample {
73                   __u32 size; /* Size of this structure (for compatibility checking) */
74                   __u16 ins_lat;          /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
75                   __u16 p_stage_cyc;      /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
76                   __u64 ip;
77                   __s32 pid;
78                   __s32 tid;
79                   __u64 time;
80                   __u64 addr;
81                   __u64 id;
82                   __u64 stream_id;
83                   __u64 period;
84                   __u64 weight;           /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
85                   __u64 transaction;      /* Refer PERF_SAMPLE_TRANSACTION in <linux/perf_event.h> */
86                   __u64 insn_cnt; /* For instructions-per-cycle (IPC) */
87                   __u64 cyc_cnt;          /* For instructions-per-cycle (IPC) */
88                   __s32 cpu;
89                   __u32 flags;            /* Refer PERF_DLFILTER_FLAG_* above */
90                   __u64 data_src;         /* Refer PERF_SAMPLE_DATA_SRC in <linux/perf_event.h> */
91                   __u64 phys_addr;        /* Refer PERF_SAMPLE_PHYS_ADDR in <linux/perf_event.h> */
92                   __u64 data_page_size;   /* Refer PERF_SAMPLE_DATA_PAGE_SIZE in <linux/perf_event.h> */
93                   __u64 code_page_size;   /* Refer PERF_SAMPLE_CODE_PAGE_SIZE in <linux/perf_event.h> */
94                   __u64 cgroup;           /* Refer PERF_SAMPLE_CGROUP in <linux/perf_event.h> */
95                   __u8  cpumode;          /* Refer CPUMODE_MASK etc in <linux/perf_event.h> */
96                   __u8  addr_correlates_sym; /* True => resolve_addr() can be called */
97                   __u16 misc;             /* Refer perf_event_header in <linux/perf_event.h> */
98                   __u32 raw_size;         /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
99                   const void *raw_data;   /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
100                   __u64 brstack_nr;       /* Number of brstack entries */
101                   const struct perf_branch_entry *brstack; /* Refer <linux/perf_event.h> */
102                   __u64 raw_callchain_nr; /* Number of raw_callchain entries */
103                   const __u64 *raw_callchain; /* Refer <linux/perf_event.h> */
104                   const char *event;
105                   __s32 machine_pid;
106                   __s32 vcpu;
107           };
108
109       Note: machine_pid and vcpu are not original members, but were added
110       together later. size can be used to determine their presence at run
111       time. PERF_DLFILTER_HAS_MACHINE_PID will be defined if they are present
112       at compile time. For example:
113
114           #include <perf/perf_dlfilter.h>
115           #include <stddef.h>
116           #include <stdbool.h>
117
118           static inline bool have_machine_pid(const struct perf_dlfilter_sample *sample)
119           {
120           #ifdef PERF_DLFILTER_HAS_MACHINE_PID
121                   return sample->size >= offsetof(struct perf_dlfilter_sample, vcpu) + sizeof(sample->vcpu);
122           #else
123                   return false;
124           #endif
125           }
126
127   The perf_dlfilter_fns structure
128       The perf_dlfilter_fns structure is populated with function pointers
129       when the file is loaded. The functions can be called by filter_event or
130       filter_event_early.
131
132           struct perf_dlfilter_fns {
133                   const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);
134                   const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);
135                   char **(*args)(void *ctx, int *dlargc);
136                   __s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);
137                   const __u8 *(*insn)(void *ctx, __u32 *length);
138                   const char *(*srcline)(void *ctx, __u32 *line_number);
139                   struct perf_event_attr *(*attr)(void *ctx);
140                   __s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);
141                   void (*al_cleanup)(void *ctx, struct perf_dlfilter_al *al);
142                   void *(*reserved[119])(void *);
143           };
144
145       resolve_ip returns information about ip.
146
147       resolve_addr returns information about addr (if addr_correlates_sym).
148
149       args returns arguments from --dlarg options.
150
151       resolve_address provides information about address. al→size must be set
152       before calling. Returns 0 on success, -1 otherwise. Call al_cleanup()
153       (if present, see below) when al data is no longer needed.
154
155       insn returns instruction bytes and length.
156
157       srcline return source file name and line number.
158
159       attr returns perf_event_attr, refer <linux/perf_event.h>.
160
161       object_code reads object code and returns the number of bytes read.
162
163       al_cleanup must be called (if present, so check
164       perf_dlfilter_fns.al_cleanup != NULL) after resolve_address() to free
165       any associated resources.
166
167       Do not assume pointers obtained via perf_dlfilter_fns are valid
168       (dereferenceable) after filter_event and filter_event_early return.
169
170   The perf_dlfilter_al structure
171       The perf_dlfilter_al structure contains information about an address.
172
173           /*
174            * Address location (as per perf script)
175            */
176           struct perf_dlfilter_al {
177                   __u32 size; /* Size of this structure (for compatibility checking) */
178                   __u32 symoff;
179                   const char *sym;
180                   __u64 addr; /* Mapped address (from dso) */
181                   __u64 sym_start;
182                   __u64 sym_end;
183                   const char *dso;
184                   __u8  sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */
185                   __u8  is_64_bit; /* Only valid if dso is not NULL */
186                   __u8  is_kernel_ip; /* True if in kernel space */
187                   __u32 buildid_size;
188                   __u8 *buildid;
189                   /* Below members are only populated by resolve_ip() */
190                   __u8 filtered; /* true if this sample event will be filtered out */
191                   const char *comm;
192                   void *priv; /* Private data. Do not change */
193           };
194
195       Do not assume data referenced by pointers in struct perf_dlfilter_al is
196       valid (dereferenceable) after filter_event and filter_event_early
197       return.
198
199   perf_dlfilter_sample flags
200       The flags member of perf_dlfilter_sample corresponds with the flags
201       field of perf script. The bits of the flags are as follows:
202
203           /* Definitions for perf_dlfilter_sample flags */
204           enum {
205                   PERF_DLFILTER_FLAG_BRANCH       = 1ULL << 0,
206                   PERF_DLFILTER_FLAG_CALL         = 1ULL << 1,
207                   PERF_DLFILTER_FLAG_RETURN       = 1ULL << 2,
208                   PERF_DLFILTER_FLAG_CONDITIONAL  = 1ULL << 3,
209                   PERF_DLFILTER_FLAG_SYSCALLRET   = 1ULL << 4,
210                   PERF_DLFILTER_FLAG_ASYNC        = 1ULL << 5,
211                   PERF_DLFILTER_FLAG_INTERRUPT    = 1ULL << 6,
212                   PERF_DLFILTER_FLAG_TX_ABORT     = 1ULL << 7,
213                   PERF_DLFILTER_FLAG_TRACE_BEGIN  = 1ULL << 8,
214                   PERF_DLFILTER_FLAG_TRACE_END    = 1ULL << 9,
215                   PERF_DLFILTER_FLAG_IN_TX        = 1ULL << 10,
216                   PERF_DLFILTER_FLAG_VMENTRY      = 1ULL << 11,
217                   PERF_DLFILTER_FLAG_VMEXIT       = 1ULL << 12,
218           };
219

EXAMPLE

221       Filter out everything except branches from "foo" to "bar":
222
223           #include <perf/perf_dlfilter.h>
224           #include <string.h>
225
226           struct perf_dlfilter_fns perf_dlfilter_fns;
227
228           int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
229           {
230                   const struct perf_dlfilter_al *al;
231                   const struct perf_dlfilter_al *addr_al;
232
233                   if (!sample->ip || !sample->addr_correlates_sym)
234                           return 1;
235
236                   al = perf_dlfilter_fns.resolve_ip(ctx);
237                   if (!al || !al->sym || strcmp(al->sym, "foo"))
238                           return 1;
239
240                   addr_al = perf_dlfilter_fns.resolve_addr(ctx);
241                   if (!addr_al || !addr_al->sym || strcmp(addr_al->sym, "bar"))
242                           return 1;
243
244                   return 0;
245           }
246
247       To build the shared object, assuming perf has been installed for the
248       local user i.e. perf_dlfilter.h is in ~/include/perf :
249
250           gcc -c -I ~/include -fpic dlfilter-example.c
251           gcc -shared -o dlfilter-example.so dlfilter-example.o
252
253       To use the filter with perf script:
254
255           perf script --dlfilter dlfilter-example.so
256

NOTES

258       The dlfilter .so file will be dependent on shared libraries. If those
259       change, it may be necessary to rebuild the .so. Also there may be
260       unexpected results if the .so uses different versions of the shared
261       libraries that perf uses. Versions can be checked using the ldd
262       command.
263

SEE ALSO

265       perf-script(1)
266
267
268
269perf                              11/28/2023                  PERF-DLFILTER(1)
Impressum