1 perf-dlfilter(1) 2 ================ 3 4 NAME 5 ---- 6 perf-dlfilter - Filter sample events using a dynamically loaded shared 7 object file 8 9 SYNOPSIS 10 -------- 11 [verse] 12 'perf script' [--dlfilter file.so ] [ --dlarg arg ]... 13 14 DESCRIPTION 15 ----------- 16 17 This option is used to process data through a custom filter provided by a 18 dynamically loaded shared object file. Arguments can be passed using --dlarg 19 and retrieved using perf_dlfilter_fns.args(). 20 21 If 'file.so' does not contain "/", then it will be found either in the current 22 directory, or perf tools exec path which is ~/libexec/perf-core/dlfilters for 23 a local build and install (refer perf --exec-path), or the dynamic linker 24 paths. 25 26 API 27 --- 28 29 The API for filtering consists of the following: 30 31 [source,c] 32 ---- 33 #include <perf/perf_dlfilter.h> 34 35 struct perf_dlfilter_fns perf_dlfilter_fns; 36 37 int start(void **data, void *ctx); 38 int stop(void *data, void *ctx); 39 int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx); 40 int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx); 41 const char *filter_description(const char **long_description); 42 ---- 43 44 If implemented, 'start' will be called at the beginning, before any 45 calls to 'filter_event' or 'filter_event_early'. Return 0 to indicate success, 46 or return a negative error code. '*data' can be assigned for use by other 47 functions. 'ctx' is needed for calls to perf_dlfilter_fns, but most 48 perf_dlfilter_fns are not valid when called from 'start'. 49 50 If 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 52 return a negative error code. 'data' is set by 'start'. 'ctx' is needed 53 for calls to perf_dlfilter_fns, but most perf_dlfilter_fns are not valid 54 when called from 'stop'. 55 56 If implemented, 'filter_event' will be called for each sample event. 57 Return 0 to keep the sample event, 1 to filter it out, or return a negative 58 error 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 62 internal filtering. 63 64 If implemented, 'filter_description' should return a one-line description 65 of the filter, and optionally a longer description. 66 67 Do not assume the 'sample' argument is valid (dereferenceable) 68 after 'filter_event' and 'filter_event_early' return. 69 70 Do not assume data referenced by pointers in struct perf_dlfilter_sample 71 is valid (dereferenceable) after 'filter_event' and 'filter_event_early' return. 72 73 The perf_dlfilter_sample structure 74 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 75 76 'filter_event' and 'filter_event_early' are passed a perf_dlfilter_sample 77 structure, 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 */ 83 struct 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 121 Note: '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. 123 PERF_DLFILTER_HAS_MACHINE_PID will be defined if they are present at compile time. 124 For example: 125 [source,c] 126 ---- 127 #include <perf/perf_dlfilter.h> 128 #include <stddef.h> 129 #include <stdbool.h> 130 131 static inline bool have_machine_pid(const struct perf_dlfilter_sample *sample) 132 { 133 #ifdef PERF_DLFILTER_HAS_MACHINE_PID 134 return sample->size >= offsetof(struct perf_dlfilter_sample, vcpu) + sizeof(sample->vcpu); 135 #else 136 return false; 137 #endif 138 } 139 ---- 140 141 The perf_dlfilter_fns structure 142 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 143 144 The 'perf_dlfilter_fns' structure is populated with function pointers when the 145 file is loaded. The functions can be called by 'filter_event' or 146 'filter_event_early'. 147 148 [source,c] 149 ---- 150 struct 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 set 171 before calling. Returns 0 on success, -1 otherwise. Call al_cleanup() (if present, 172 see 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) 183 after resolve_address() to free any associated resources. 184 185 Do not assume pointers obtained via perf_dlfilter_fns are valid (dereferenceable) 186 after 'filter_event' and 'filter_event_early' return. 187 188 The perf_dlfilter_al structure 189 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 190 191 The 'perf_dlfilter_al' structure contains information about an address. 192 193 [source,c] 194 ---- 195 /* 196 * Address location (as per perf script) 197 */ 198 struct 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 218 Do not assume data referenced by pointers in struct perf_dlfilter_al 219 is valid (dereferenceable) after 'filter_event' and 'filter_event_early' return. 220 221 perf_dlfilter_sample flags 222 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 223 224 The 'flags' member of 'perf_dlfilter_sample' corresponds with the flags field 225 of perf script. The bits of the flags are as follows: 226 227 [source,c] 228 ---- 229 /* Definitions for perf_dlfilter_sample flags */ 230 enum { 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 247 EXAMPLE 248 ------- 249 250 Filter out everything except branches from "foo" to "bar": 251 252 [source,c] 253 ---- 254 #include <perf/perf_dlfilter.h> 255 #include <string.h> 256 257 struct perf_dlfilter_fns perf_dlfilter_fns; 258 259 int 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 279 To build the shared object, assuming perf has been installed for the local user 280 i.e. perf_dlfilter.h is in ~/include/perf : 281 282 gcc -c -I ~/include -fpic dlfilter-example.c 283 gcc -shared -o dlfilter-example.so dlfilter-example.o 284 285 To use the filter with perf script: 286 287 perf script --dlfilter dlfilter-example.so 288 289 NOTES 290 ----- 291 292 The dlfilter .so file will be dependent on shared libraries. If those change, 293 it may be necessary to rebuild the .so. Also there may be unexpected results 294 if the .so uses different versions of the shared libraries that perf uses. 295 Versions can be checked using the ldd command. 296 297 SEE ALSO 298 -------- 299 linkperf:perf-script[1]
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.