Back to home page

OSCL-LXR

 
 

    


0001 perf-dlfilter(1)
0002 ================
0003 
0004 NAME
0005 ----
0006 perf-dlfilter - Filter sample events using a dynamically loaded shared
0007 object file
0008 
0009 SYNOPSIS
0010 --------
0011 [verse]
0012 'perf script' [--dlfilter file.so ] [ --dlarg arg ]...
0013 
0014 DESCRIPTION
0015 -----------
0016 
0017 This option is used to process data through a custom filter provided by a
0018 dynamically loaded shared object file. Arguments can be passed using --dlarg
0019 and retrieved using perf_dlfilter_fns.args().
0020 
0021 If 'file.so' does not contain "/", then it will be found either in the current
0022 directory, or perf tools exec path which is ~/libexec/perf-core/dlfilters for
0023 a local build and install (refer perf --exec-path), or the dynamic linker
0024 paths.
0025 
0026 API
0027 ---
0028 
0029 The API for filtering consists of the following:
0030 
0031 [source,c]
0032 ----
0033 #include <perf/perf_dlfilter.h>
0034 
0035 struct perf_dlfilter_fns perf_dlfilter_fns;
0036 
0037 int start(void **data, void *ctx);
0038 int stop(void *data, void *ctx);
0039 int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
0040 int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
0041 const char *filter_description(const char **long_description);
0042 ----
0043 
0044 If implemented, 'start' will be called at the beginning, before any
0045 calls to 'filter_event' or 'filter_event_early'. Return 0 to indicate success,
0046 or return a negative error code. '*data' can be assigned for use by other
0047 functions. 'ctx' is needed for calls to perf_dlfilter_fns, but most
0048 perf_dlfilter_fns are not valid when called from 'start'.
0049 
0050 If implemented, 'stop' will be called at the end, after any calls to
0051 'filter_event' or 'filter_event_early'. Return 0 to indicate success, or
0052 return a negative error code. 'data' is set by 'start'. 'ctx' is needed
0053 for calls to perf_dlfilter_fns, but most perf_dlfilter_fns are not valid
0054 when called from 'stop'.
0055 
0056 If implemented, 'filter_event' will be called for each sample event.
0057 Return 0 to keep the sample event, 1 to filter it out, or return a negative
0058 error code. 'data' is set by 'start'. 'ctx' is needed for calls to
0059 'perf_dlfilter_fns'.
0060 
0061 'filter_event_early' is the same as 'filter_event' except it is called before
0062 internal filtering.
0063 
0064 If implemented, 'filter_description' should return a one-line description
0065 of the filter, and optionally a longer description.
0066 
0067 The perf_dlfilter_sample structure
0068 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0069 
0070 'filter_event' and 'filter_event_early' are passed a perf_dlfilter_sample
0071 structure, which contains the following fields:
0072 [source,c]
0073 ----
0074 /*
0075  * perf sample event information (as per perf script and <linux/perf_event.h>)
0076  */
0077 struct perf_dlfilter_sample {
0078         __u32 size; /* Size of this structure (for compatibility checking) */
0079         __u16 ins_lat;          /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
0080         __u16 p_stage_cyc;      /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
0081         __u64 ip;
0082         __s32 pid;
0083         __s32 tid;
0084         __u64 time;
0085         __u64 addr;
0086         __u64 id;
0087         __u64 stream_id;
0088         __u64 period;
0089         __u64 weight;           /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
0090         __u64 transaction;      /* Refer PERF_SAMPLE_TRANSACTION in <linux/perf_event.h> */
0091         __u64 insn_cnt; /* For instructions-per-cycle (IPC) */
0092         __u64 cyc_cnt;          /* For instructions-per-cycle (IPC) */
0093         __s32 cpu;
0094         __u32 flags;            /* Refer PERF_DLFILTER_FLAG_* above */
0095         __u64 data_src;         /* Refer PERF_SAMPLE_DATA_SRC in <linux/perf_event.h> */
0096         __u64 phys_addr;        /* Refer PERF_SAMPLE_PHYS_ADDR in <linux/perf_event.h> */
0097         __u64 data_page_size;   /* Refer PERF_SAMPLE_DATA_PAGE_SIZE in <linux/perf_event.h> */
0098         __u64 code_page_size;   /* Refer PERF_SAMPLE_CODE_PAGE_SIZE in <linux/perf_event.h> */
0099         __u64 cgroup;           /* Refer PERF_SAMPLE_CGROUP in <linux/perf_event.h> */
0100         __u8  cpumode;          /* Refer CPUMODE_MASK etc in <linux/perf_event.h> */
0101         __u8  addr_correlates_sym; /* True => resolve_addr() can be called */
0102         __u16 misc;             /* Refer perf_event_header in <linux/perf_event.h> */
0103         __u32 raw_size;         /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
0104         const void *raw_data;   /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
0105         __u64 brstack_nr;       /* Number of brstack entries */
0106         const struct perf_branch_entry *brstack; /* Refer <linux/perf_event.h> */
0107         __u64 raw_callchain_nr; /* Number of raw_callchain entries */
0108         const __u64 *raw_callchain; /* Refer <linux/perf_event.h> */
0109         const char *event;
0110         __s32 machine_pid;
0111         __s32 vcpu;
0112 };
0113 ----
0114 
0115 Note: 'machine_pid' and 'vcpu' are not original members, but were added together later.
0116 'size' can be used to determine their presence at run time.
0117 PERF_DLFILTER_HAS_MACHINE_PID will be defined if they are present at compile time.
0118 For example:
0119 [source,c]
0120 ----
0121 #include <perf/perf_dlfilter.h>
0122 #include <stddef.h>
0123 #include <stdbool.h>
0124 
0125 static inline bool have_machine_pid(const struct perf_dlfilter_sample *sample)
0126 {
0127 #ifdef PERF_DLFILTER_HAS_MACHINE_PID
0128         return sample->size >= offsetof(struct perf_dlfilter_sample, vcpu) + sizeof(sample->vcpu);
0129 #else
0130         return false;
0131 #endif
0132 }
0133 ----
0134 
0135 The perf_dlfilter_fns structure
0136 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0137 
0138 The 'perf_dlfilter_fns' structure is populated with function pointers when the
0139 file is loaded. The functions can be called by 'filter_event' or
0140 'filter_event_early'.
0141 
0142 [source,c]
0143 ----
0144 struct perf_dlfilter_fns {
0145         const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);
0146         const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);
0147         char **(*args)(void *ctx, int *dlargc);
0148         __s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);
0149         const __u8 *(*insn)(void *ctx, __u32 *length);
0150         const char *(*srcline)(void *ctx, __u32 *line_number);
0151         struct perf_event_attr *(*attr)(void *ctx);
0152         __s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);
0153         void *(*reserved[120])(void *);
0154 };
0155 ----
0156 
0157 'resolve_ip' returns information about ip.
0158 
0159 'resolve_addr' returns information about addr (if addr_correlates_sym).
0160 
0161 'args' returns arguments from --dlarg options.
0162 
0163 'resolve_address' provides information about 'address'. al->size must be set
0164 before calling. Returns 0 on success, -1 otherwise.
0165 
0166 'insn' returns instruction bytes and length.
0167 
0168 'srcline' return source file name and line number.
0169 
0170 'attr' returns perf_event_attr, refer <linux/perf_event.h>.
0171 
0172 'object_code' reads object code and returns the number of bytes read.
0173 
0174 The perf_dlfilter_al structure
0175 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0176 
0177 The 'perf_dlfilter_al' structure contains information about an address.
0178 
0179 [source,c]
0180 ----
0181 /*
0182  * Address location (as per perf script)
0183  */
0184 struct perf_dlfilter_al {
0185         __u32 size; /* Size of this structure (for compatibility checking) */
0186         __u32 symoff;
0187         const char *sym;
0188         __u64 addr; /* Mapped address (from dso) */
0189         __u64 sym_start;
0190         __u64 sym_end;
0191         const char *dso;
0192         __u8  sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */
0193         __u8  is_64_bit; /* Only valid if dso is not NULL */
0194         __u8  is_kernel_ip; /* True if in kernel space */
0195         __u32 buildid_size;
0196         __u8 *buildid;
0197         /* Below members are only populated by resolve_ip() */
0198         __u8 filtered; /* true if this sample event will be filtered out */
0199         const char *comm;
0200 };
0201 ----
0202 
0203 perf_dlfilter_sample flags
0204 ~~~~~~~~~~~~~~~~~~~~~~~~~~
0205 
0206 The 'flags' member of 'perf_dlfilter_sample' corresponds with the flags field
0207 of perf script. The bits of the flags are as follows:
0208 
0209 [source,c]
0210 ----
0211 /* Definitions for perf_dlfilter_sample flags */
0212 enum {
0213         PERF_DLFILTER_FLAG_BRANCH       = 1ULL << 0,
0214         PERF_DLFILTER_FLAG_CALL         = 1ULL << 1,
0215         PERF_DLFILTER_FLAG_RETURN       = 1ULL << 2,
0216         PERF_DLFILTER_FLAG_CONDITIONAL  = 1ULL << 3,
0217         PERF_DLFILTER_FLAG_SYSCALLRET   = 1ULL << 4,
0218         PERF_DLFILTER_FLAG_ASYNC        = 1ULL << 5,
0219         PERF_DLFILTER_FLAG_INTERRUPT    = 1ULL << 6,
0220         PERF_DLFILTER_FLAG_TX_ABORT     = 1ULL << 7,
0221         PERF_DLFILTER_FLAG_TRACE_BEGIN  = 1ULL << 8,
0222         PERF_DLFILTER_FLAG_TRACE_END    = 1ULL << 9,
0223         PERF_DLFILTER_FLAG_IN_TX        = 1ULL << 10,
0224         PERF_DLFILTER_FLAG_VMENTRY      = 1ULL << 11,
0225         PERF_DLFILTER_FLAG_VMEXIT       = 1ULL << 12,
0226 };
0227 ----
0228 
0229 EXAMPLE
0230 -------
0231 
0232 Filter out everything except branches from "foo" to "bar":
0233 
0234 [source,c]
0235 ----
0236 #include <perf/perf_dlfilter.h>
0237 #include <string.h>
0238 
0239 struct perf_dlfilter_fns perf_dlfilter_fns;
0240 
0241 int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
0242 {
0243         const struct perf_dlfilter_al *al;
0244         const struct perf_dlfilter_al *addr_al;
0245 
0246         if (!sample->ip || !sample->addr_correlates_sym)
0247                 return 1;
0248 
0249         al = perf_dlfilter_fns.resolve_ip(ctx);
0250         if (!al || !al->sym || strcmp(al->sym, "foo"))
0251                 return 1;
0252 
0253         addr_al = perf_dlfilter_fns.resolve_addr(ctx);
0254         if (!addr_al || !addr_al->sym || strcmp(addr_al->sym, "bar"))
0255                 return 1;
0256 
0257         return 0;
0258 }
0259 ----
0260 
0261 To build the shared object, assuming perf has been installed for the local user
0262 i.e. perf_dlfilter.h is in ~/include/perf :
0263 
0264         gcc -c -I ~/include -fpic dlfilter-example.c
0265         gcc -shared -o dlfilter-example.so dlfilter-example.o
0266 
0267 To use the filter with perf script:
0268 
0269         perf script --dlfilter dlfilter-example.so
0270 
0271 NOTES
0272 -----
0273 
0274 The dlfilter .so file will be dependent on shared libraries. If those change,
0275 it may be necessary to rebuild the .so. Also there may be unexpected results
0276 if the .so uses different versions of the shared libraries that perf uses.
0277 Versions can be checked using the ldd command.
0278 
0279 SEE ALSO
0280 --------
0281 linkperf:perf-script[1]