PERF-DLFILTER(1) perf Manual PERF-DLFILTER(1)

perf-dlfilter - فیلتر کردن رویدادهای نمونه‌برداری با استفاده از یک فایل شیء مشترک بارگذاری‌شده به‌صورت پویا

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

این گزینه برای پردازش داده‌ها از طریق یک فیلتر سفارشی فراهم‌شده توسط یک فایل شیء مشترک (shared object) بارگذاری‌شده به‌صورت پویا استفاده می‌شود. آرگومان‌ها را می‌توان با استفاده از --dlarg ارسال کرد و با استفاده از perf_dlfilter_fns.args() بازیابی نمود.

اگر file.so شامل «/» نباشد، در دایرکتوری جاری یا در مسیر اجرایی ابزارهای perf که برای ساخت و نصب محلی ~/libexec/perf-core/dlfilters است (رجوع کنید به perf --exec-path)، یا در مسیرهای پیونددهندهٔ پویا (dynamic linker) جستجو خواهد شد.

رابط برنامه‌نویسی (API) برای فیلتر کردن شامل موارد زیر است:

#include <perf/perf_dlfilter.h>
struct perf_dlfilter_fns perf_dlfilter_fns;
int start(void **data, void *ctx);
int stop(void *data, void *ctx);
int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
const char *filter_description(const char **long_description);

در صورت پیاده‌سازی، start در ابتدا، پیش از هر فراخوانی به filter_event یا filter_event_early فراخوانی خواهد شد. برای اعلام موفقیت 0 یا یک کد خطای منفی را برگردانید. می‌توان *data را برای استفاده توسط سایر توابع مقداردهی کرد. آرگومان ctx برای فراخوانی‌های perf_dlfilter_fns مورد نیاز است، اما اکثر توابع perf_dlfilter_fns هنگام فراخوانی از درون start معتبر نیستند.

در صورت پیاده‌سازی، stop در انتها، پس از هرگونه فراخوانی به filter_event یا filter_event_early فراخوانی خواهد شد. برای اعلام موفقیت 0 یا یک کد خطای منفی را برگردانید. مقدار data توسط start تنظیم می‌شود. آرگومان ctx برای فراخوانی‌های perf_dlfilter_fns لازم است، اما بیشتر توابع perf_dlfilter_fns هنگام فراخوانی از درون stop معتبر نیستند.

در صورت پیاده‌سازی، filter_event برای هر رویداد نمونه‌برداری فراخوانی خواهد شد. برای نگه‌داشتن رویداد نمونه‌برداری 0، برای فیلتر کردن (نادیده گرفتن) آن 1، یا یک کد خطای منفی را برگردانید. مقدار data توسط start تنظیم می‌شود. آرگومان ctx برای فراخوانی‌های perf_dlfilter_fns مورد نیاز است.

تابع filter_event_early مشابه filter_event است، با این تفاوت که پیش از فیلترگذاری داخلی فراخوانی می‌شود.

در صورت پیاده‌سازی، filter_description باید یک توصیف یک‌خطی از فیلتر و در صورت تمایل یک توصیف طولانی‌تر را بازگرداند.

فرض نکنید که آرگومان sample پس از بازگشت توابع filter_event و filter_event_early همچنان معتبر (قابل ارجاع‌زدایی) باقی می‌ماند.

فرض نکنید که داده‌های مورد اشاره توسط اشاره‌گرها در struct perf_dlfilter_sample پس از بازگشت توابع filter_event و filter_event_early همچنان معتبر (قابل ارجاع‌زدایی) باقی می‌مانند.

به توابع filter_event و filter_event_early یک ساختار perf_dlfilter_sample ارسال می‌شود که شامل فیلدهای زیر است:

/*
 * perf sample event information (as per perf script and <linux/perf_event.h>)
 */
struct perf_dlfilter_sample {
        __u32 size; /* Size of this structure (for compatibility checking) */
        __u16 ins_lat;          /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
        __u16 p_stage_cyc;      /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
        __u64 ip;
        __s32 pid;
        __s32 tid;
        __u64 time;
        __u64 addr;
        __u64 id;
        __u64 stream_id;
        __u64 period;
        __u64 weight;           /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
        __u64 transaction;      /* Refer PERF_SAMPLE_TRANSACTION in <linux/perf_event.h> */
        __u64 insn_cnt; /* For instructions-per-cycle (IPC) */
        __u64 cyc_cnt;          /* For instructions-per-cycle (IPC) */
        __s32 cpu;
        __u32 flags;            /* Refer PERF_DLFILTER_FLAG_* above */
        __u64 data_src;         /* Refer PERF_SAMPLE_DATA_SRC in <linux/perf_event.h> */
        __u64 phys_addr;        /* Refer PERF_SAMPLE_PHYS_ADDR in <linux/perf_event.h> */
        __u64 data_page_size;   /* Refer PERF_SAMPLE_DATA_PAGE_SIZE in <linux/perf_event.h> */
        __u64 code_page_size;   /* Refer PERF_SAMPLE_CODE_PAGE_SIZE in <linux/perf_event.h> */
        __u64 cgroup;           /* Refer PERF_SAMPLE_CGROUP in <linux/perf_event.h> */
        __u8  cpumode;          /* Refer CPUMODE_MASK etc in <linux/perf_event.h> */
        __u8  addr_correlates_sym; /* True => resolve_addr() can be called */
        __u16 misc;             /* Refer perf_event_header in <linux/perf_event.h> */
        __u32 raw_size;         /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
        const void *raw_data;   /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
        __u64 brstack_nr;       /* Number of brstack entries */
        const struct perf_branch_entry *brstack; /* Refer <linux/perf_event.h> */
        __u64 raw_callchain_nr; /* Number of raw_callchain entries */
        const __u64 *raw_callchain; /* Refer <linux/perf_event.h> */
        const char *event;
        __s32 machine_pid;
        __s32 vcpu;
};

نکته: machine_pid و vcpu از اعضای اولیه نبوده‌اند، بلکه بعداً با یکدیگر اضافه شده‌اند. از size می‌توان برای تعیین وجود آن‌ها در زمان اجرا استفاده کرد. در صورتی که آن‌ها در زمان کامپایل وجود داشته باشند، PERF_DLFILTER_HAS_MACHINE_PID تعریف خواهد شد. برای مثال:

#include <perf/perf_dlfilter.h>
#include <stddef.h>
#include <stdbool.h>
static inline bool have_machine_pid(const struct perf_dlfilter_sample *sample)
{
#ifdef PERF_DLFILTER_HAS_MACHINE_PID
        return sample->size >= offsetof(struct perf_dlfilter_sample, vcpu) + sizeof(sample->vcpu);
#else
        return false;
#endif
}

ساختار perf_dlfilter_fns هنگام بارگذاری فایل با اشاره‌گرهای توابع پر می‌شود. این توابع می‌توانند توسط filter_event یا filter_event_early فراخوانی شوند.

struct perf_dlfilter_fns {
        const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);
        const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);
        char **(*args)(void *ctx, int *dlargc);
        __s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);
        const __u8 *(*insn)(void *ctx, __u32 *length);
        const char *(*srcline)(void *ctx, __u32 *line_number);
        struct perf_event_attr *(*attr)(void *ctx);
        __s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);
        void (*al_cleanup)(void *ctx, struct perf_dlfilter_al *al);
        void *(*reserved[119])(void *);
};

تابع resolve_ip اطلاعاتی دربارهٔ ip بازمی‌گرداند.

تابع resolve_addr اطلاعاتی دربارهٔ addr بازمی‌گرداند (در صورت برقرار بودن addr_correlates_sym).

تابع args آرگومان‌های دریافتی از گزینه‌های --dlarg را بازمی‌گرداند.

تابع resolve_address اطلاعاتی دربارهٔ address فراهم می‌کند. مقدار al→size باید پیش از فراخوانی تنظیم شود. در صورت موفقیت 0 و در غیر این صورت -1 برمی‌گرداند. هنگامی که دیگر به داده‌های al نیازی نبود، al_cleanup() را (در صورت وجود، بخش زیر را ببینید) فراخوانی کنید.

تابع insn بایت‌های دستورالعمل و طول آن را بازمی‌گرداند.

تابع srcline نام فایل منبع و شمارهٔ خط را بازمی‌گرداند.

تابع attr ساختار perf_event_attr را بازمی‌گرداند؛ رجوع کنید به <linux/perf_event.h>.

تابع object_code کد شیء (object code) را می‌خواند و تعداد بایت‌های خوانده‌شده را بازمی‌گرداند.

تابع al_cleanup باید پس از resolve_address() فراخوانی شود (در صورت وجود؛ بنابراین perf_dlfilter_fns.al_cleanup != NULL را بررسی کنید) تا منابع تخصیص‌یافته آزاد شوند.

فرض نکنید اشاره‌گرهای به‌دست‌آمده از طریق perf_dlfilter_fns پس از بازگشت filter_event و filter_event_early معتبر (قابل ارجاع‌زدایی) باقی می‌مانند.

ساختار perf_dlfilter_al حاوی اطلاعاتی دربارهٔ یک آدرس است.

/*
 * Address location (as per perf script)
 */
struct perf_dlfilter_al {
        __u32 size; /* Size of this structure (for compatibility checking) */
        __u32 symoff;
        const char *sym;
        __u64 addr; /* Mapped address (from dso) */
        __u64 sym_start;
        __u64 sym_end;
        const char *dso;
        __u8  sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */
        __u8  is_64_bit; /* Only valid if dso is not NULL */
        __u8  is_kernel_ip; /* True if in kernel space */
        __u32 buildid_size;
        __u8 *buildid;
        /* Below members are only populated by resolve_ip() */
        __u8 filtered; /* true if this sample event will be filtered out */
        const char *comm;
        void *priv; /* Private data. Do not change */
};

فرض نکنید داده‌های مورد اشاره توسط اشاره‌گرها در struct perf_dlfilter_al پس از بازگشت filter_event و filter_event_early معتبر (قابل ارجاع‌زدایی) باقی می‌مانند.

عضو flags در ساختار perf_dlfilter_sample متناظر با فیلد flags در perf script است. بیت‌های این پرچم‌ها به شرح زیر است:

/* Definitions for perf_dlfilter_sample flags */
enum {
        PERF_DLFILTER_FLAG_BRANCH       = 1ULL << 0,
        PERF_DLFILTER_FLAG_CALL         = 1ULL << 1,
        PERF_DLFILTER_FLAG_RETURN       = 1ULL << 2,
        PERF_DLFILTER_FLAG_CONDITIONAL  = 1ULL << 3,
        PERF_DLFILTER_FLAG_SYSCALLRET   = 1ULL << 4,
        PERF_DLFILTER_FLAG_ASYNC        = 1ULL << 5,
        PERF_DLFILTER_FLAG_INTERRUPT    = 1ULL << 6,
        PERF_DLFILTER_FLAG_TX_ABORT     = 1ULL << 7,
        PERF_DLFILTER_FLAG_TRACE_BEGIN  = 1ULL << 8,
        PERF_DLFILTER_FLAG_TRACE_END    = 1ULL << 9,
        PERF_DLFILTER_FLAG_IN_TX        = 1ULL << 10,
        PERF_DLFILTER_FLAG_VMENTRY      = 1ULL << 11,
        PERF_DLFILTER_FLAG_VMEXIT       = 1ULL << 12,
};

فیلتر کردن همه‌چیز به جز انشعاب‌ها از "foo" به "bar":

#include <perf/perf_dlfilter.h>
#include <string.h>
struct perf_dlfilter_fns perf_dlfilter_fns;
int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
{
        const struct perf_dlfilter_al *al;
        const struct perf_dlfilter_al *addr_al;
        if (!sample->ip || !sample->addr_correlates_sym)
                return 1;
        al = perf_dlfilter_fns.resolve_ip(ctx);
        if (!al || !al->sym || strcmp(al->sym, "foo"))
                return 1;
        addr_al = perf_dlfilter_fns.resolve_addr(ctx);
        if (!addr_al || !addr_al->sym || strcmp(addr_al->sym, "bar"))
                return 1;
        return 0;
}

برای ساخت شیء مشترک، با فرض اینکه perf برای کاربر محلی نصب شده است (یعنی perf_dlfilter.h در ~/include/perf قرار دارد):

gcc -c -I ~/include -fpic dlfilter-example.c
gcc -shared -o dlfilter-example.so dlfilter-example.o

برای استفاده از فیلتر به همراه perf script:

perf script --dlfilter dlfilter-example.so

فایل dlfilter .so به کتابخانه‌های مشترک وابسته خواهد بود. در صورت تغییر آن‌ها، ممکن است بازسازی فایل .so ضروری باشد. همچنین اگر فایل .so از نسخه‌های متفاوتی از کتابخانه‌های مشترک نسبت به آنچه perf استفاده می‌کند بهره ببرد، ممکن است نتایج غیرمنتظره‌ای به وجود آید. نسخه‌ها را می‌توان با استفاده از دستور ldd بررسی کرد.

perf-script(1)

09/04/2026 perf