182b0a103SAdrian Hunter // SPDX-License-Identifier: GPL-2.0
282b0a103SAdrian Hunter /*
382b0a103SAdrian Hunter * Test v2 API for perf --dlfilter shared object
482b0a103SAdrian Hunter * Copyright (c) 2023, Intel Corporation.
582b0a103SAdrian Hunter */
682b0a103SAdrian Hunter #include <stdio.h>
782b0a103SAdrian Hunter #include <stdlib.h>
882b0a103SAdrian Hunter #include <string.h>
982b0a103SAdrian Hunter #include <stdbool.h>
1082b0a103SAdrian Hunter
1182b0a103SAdrian Hunter /*
1282b0a103SAdrian Hunter * Copy v2 API instead of including current API
1382b0a103SAdrian Hunter */
1482b0a103SAdrian Hunter #include <linux/perf_event.h>
1582b0a103SAdrian Hunter #include <linux/types.h>
1682b0a103SAdrian Hunter
1782b0a103SAdrian Hunter /*
1882b0a103SAdrian Hunter * The following macro can be used to determine if this header defines
1982b0a103SAdrian Hunter * perf_dlfilter_sample machine_pid and vcpu.
2082b0a103SAdrian Hunter */
2182b0a103SAdrian Hunter #define PERF_DLFILTER_HAS_MACHINE_PID
2282b0a103SAdrian Hunter
2382b0a103SAdrian Hunter /* Definitions for perf_dlfilter_sample flags */
2482b0a103SAdrian Hunter enum {
2582b0a103SAdrian Hunter PERF_DLFILTER_FLAG_BRANCH = 1ULL << 0,
2682b0a103SAdrian Hunter PERF_DLFILTER_FLAG_CALL = 1ULL << 1,
2782b0a103SAdrian Hunter PERF_DLFILTER_FLAG_RETURN = 1ULL << 2,
2882b0a103SAdrian Hunter PERF_DLFILTER_FLAG_CONDITIONAL = 1ULL << 3,
2982b0a103SAdrian Hunter PERF_DLFILTER_FLAG_SYSCALLRET = 1ULL << 4,
3082b0a103SAdrian Hunter PERF_DLFILTER_FLAG_ASYNC = 1ULL << 5,
3182b0a103SAdrian Hunter PERF_DLFILTER_FLAG_INTERRUPT = 1ULL << 6,
3282b0a103SAdrian Hunter PERF_DLFILTER_FLAG_TX_ABORT = 1ULL << 7,
3382b0a103SAdrian Hunter PERF_DLFILTER_FLAG_TRACE_BEGIN = 1ULL << 8,
3482b0a103SAdrian Hunter PERF_DLFILTER_FLAG_TRACE_END = 1ULL << 9,
3582b0a103SAdrian Hunter PERF_DLFILTER_FLAG_IN_TX = 1ULL << 10,
3682b0a103SAdrian Hunter PERF_DLFILTER_FLAG_VMENTRY = 1ULL << 11,
3782b0a103SAdrian Hunter PERF_DLFILTER_FLAG_VMEXIT = 1ULL << 12,
3882b0a103SAdrian Hunter };
3982b0a103SAdrian Hunter
4082b0a103SAdrian Hunter /*
4182b0a103SAdrian Hunter * perf sample event information (as per perf script and <linux/perf_event.h>)
4282b0a103SAdrian Hunter */
4382b0a103SAdrian Hunter struct perf_dlfilter_sample {
4482b0a103SAdrian Hunter __u32 size; /* Size of this structure (for compatibility checking) */
4582b0a103SAdrian Hunter __u16 ins_lat; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
4682b0a103SAdrian Hunter __u16 p_stage_cyc; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
4782b0a103SAdrian Hunter __u64 ip;
4882b0a103SAdrian Hunter __s32 pid;
4982b0a103SAdrian Hunter __s32 tid;
5082b0a103SAdrian Hunter __u64 time;
5182b0a103SAdrian Hunter __u64 addr;
5282b0a103SAdrian Hunter __u64 id;
5382b0a103SAdrian Hunter __u64 stream_id;
5482b0a103SAdrian Hunter __u64 period;
5582b0a103SAdrian Hunter __u64 weight; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
5682b0a103SAdrian Hunter __u64 transaction; /* Refer PERF_SAMPLE_TRANSACTION in <linux/perf_event.h> */
5782b0a103SAdrian Hunter __u64 insn_cnt; /* For instructions-per-cycle (IPC) */
5882b0a103SAdrian Hunter __u64 cyc_cnt; /* For instructions-per-cycle (IPC) */
5982b0a103SAdrian Hunter __s32 cpu;
6082b0a103SAdrian Hunter __u32 flags; /* Refer PERF_DLFILTER_FLAG_* above */
6182b0a103SAdrian Hunter __u64 data_src; /* Refer PERF_SAMPLE_DATA_SRC in <linux/perf_event.h> */
6282b0a103SAdrian Hunter __u64 phys_addr; /* Refer PERF_SAMPLE_PHYS_ADDR in <linux/perf_event.h> */
6382b0a103SAdrian Hunter __u64 data_page_size; /* Refer PERF_SAMPLE_DATA_PAGE_SIZE in <linux/perf_event.h> */
6482b0a103SAdrian Hunter __u64 code_page_size; /* Refer PERF_SAMPLE_CODE_PAGE_SIZE in <linux/perf_event.h> */
6582b0a103SAdrian Hunter __u64 cgroup; /* Refer PERF_SAMPLE_CGROUP in <linux/perf_event.h> */
6682b0a103SAdrian Hunter __u8 cpumode; /* Refer CPUMODE_MASK etc in <linux/perf_event.h> */
6782b0a103SAdrian Hunter __u8 addr_correlates_sym; /* True => resolve_addr() can be called */
6882b0a103SAdrian Hunter __u16 misc; /* Refer perf_event_header in <linux/perf_event.h> */
6982b0a103SAdrian Hunter __u32 raw_size; /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
7082b0a103SAdrian Hunter const void *raw_data; /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
7182b0a103SAdrian Hunter __u64 brstack_nr; /* Number of brstack entries */
7282b0a103SAdrian Hunter const struct perf_branch_entry *brstack; /* Refer <linux/perf_event.h> */
7382b0a103SAdrian Hunter __u64 raw_callchain_nr; /* Number of raw_callchain entries */
7482b0a103SAdrian Hunter const __u64 *raw_callchain; /* Refer <linux/perf_event.h> */
7582b0a103SAdrian Hunter const char *event;
7682b0a103SAdrian Hunter __s32 machine_pid;
7782b0a103SAdrian Hunter __s32 vcpu;
7882b0a103SAdrian Hunter };
7982b0a103SAdrian Hunter
8082b0a103SAdrian Hunter /*
8182b0a103SAdrian Hunter * Address location (as per perf script)
8282b0a103SAdrian Hunter */
8382b0a103SAdrian Hunter struct perf_dlfilter_al {
8482b0a103SAdrian Hunter __u32 size; /* Size of this structure (for compatibility checking) */
8582b0a103SAdrian Hunter __u32 symoff;
8682b0a103SAdrian Hunter const char *sym;
8782b0a103SAdrian Hunter __u64 addr; /* Mapped address (from dso) */
8882b0a103SAdrian Hunter __u64 sym_start;
8982b0a103SAdrian Hunter __u64 sym_end;
9082b0a103SAdrian Hunter const char *dso;
9182b0a103SAdrian Hunter __u8 sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */
9282b0a103SAdrian Hunter __u8 is_64_bit; /* Only valid if dso is not NULL */
9382b0a103SAdrian Hunter __u8 is_kernel_ip; /* True if in kernel space */
9482b0a103SAdrian Hunter __u32 buildid_size;
9582b0a103SAdrian Hunter __u8 *buildid;
9682b0a103SAdrian Hunter /* Below members are only populated by resolve_ip() */
9782b0a103SAdrian Hunter __u8 filtered; /* True if this sample event will be filtered out */
9882b0a103SAdrian Hunter const char *comm;
9982b0a103SAdrian Hunter void *priv; /* Private data (v2 API) */
10082b0a103SAdrian Hunter };
10182b0a103SAdrian Hunter
10282b0a103SAdrian Hunter struct perf_dlfilter_fns {
10382b0a103SAdrian Hunter /* Return information about ip */
10482b0a103SAdrian Hunter const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);
10582b0a103SAdrian Hunter /* Return information about addr (if addr_correlates_sym) */
10682b0a103SAdrian Hunter const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);
10782b0a103SAdrian Hunter /* Return arguments from --dlarg option */
10882b0a103SAdrian Hunter char **(*args)(void *ctx, int *dlargc);
10982b0a103SAdrian Hunter /*
11082b0a103SAdrian Hunter * Return information about address (al->size must be set before
11182b0a103SAdrian Hunter * calling). Returns 0 on success, -1 otherwise. Call al_cleanup()
11282b0a103SAdrian Hunter * when 'al' data is no longer needed.
11382b0a103SAdrian Hunter */
11482b0a103SAdrian Hunter __s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);
11582b0a103SAdrian Hunter /* Return instruction bytes and length */
11682b0a103SAdrian Hunter const __u8 *(*insn)(void *ctx, __u32 *length);
11782b0a103SAdrian Hunter /* Return source file name and line number */
11882b0a103SAdrian Hunter const char *(*srcline)(void *ctx, __u32 *line_number);
11982b0a103SAdrian Hunter /* Return perf_event_attr, refer <linux/perf_event.h> */
12082b0a103SAdrian Hunter struct perf_event_attr *(*attr)(void *ctx);
12182b0a103SAdrian Hunter /* Read object code, return numbers of bytes read */
12282b0a103SAdrian Hunter __s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);
12382b0a103SAdrian Hunter /*
12482b0a103SAdrian Hunter * If present (i.e. must check al_cleanup != NULL), call after
12582b0a103SAdrian Hunter * resolve_address() to free any associated resources. (v2 API)
12682b0a103SAdrian Hunter */
12782b0a103SAdrian Hunter void (*al_cleanup)(void *ctx, struct perf_dlfilter_al *al);
12882b0a103SAdrian Hunter /* Reserved */
12982b0a103SAdrian Hunter void *(*reserved[119])(void *);
13082b0a103SAdrian Hunter };
13182b0a103SAdrian Hunter
13282b0a103SAdrian Hunter struct perf_dlfilter_fns perf_dlfilter_fns;
13382b0a103SAdrian Hunter
13482b0a103SAdrian Hunter static int verbose;
13582b0a103SAdrian Hunter
13682b0a103SAdrian Hunter #define pr_debug(fmt, ...) do { \
13782b0a103SAdrian Hunter if (verbose > 0) \
13882b0a103SAdrian Hunter fprintf(stderr, fmt, ##__VA_ARGS__); \
13982b0a103SAdrian Hunter } while (0)
14082b0a103SAdrian Hunter
test_fail(const char * msg)14182b0a103SAdrian Hunter static int test_fail(const char *msg)
14282b0a103SAdrian Hunter {
14382b0a103SAdrian Hunter pr_debug("%s\n", msg);
14482b0a103SAdrian Hunter return -1;
14582b0a103SAdrian Hunter }
14682b0a103SAdrian Hunter
14782b0a103SAdrian Hunter #define CHECK(x) do { \
14882b0a103SAdrian Hunter if (!(x)) \
14982b0a103SAdrian Hunter return test_fail("Check '" #x "' failed\n"); \
15082b0a103SAdrian Hunter } while (0)
15182b0a103SAdrian Hunter
15282b0a103SAdrian Hunter struct filter_data {
15382b0a103SAdrian Hunter __u64 ip;
15482b0a103SAdrian Hunter __u64 addr;
15582b0a103SAdrian Hunter int do_early;
15682b0a103SAdrian Hunter int early_filter_cnt;
15782b0a103SAdrian Hunter int filter_cnt;
15882b0a103SAdrian Hunter };
15982b0a103SAdrian Hunter
16082b0a103SAdrian Hunter static struct filter_data *filt_dat;
16182b0a103SAdrian Hunter
start(void ** data,void * ctx)16282b0a103SAdrian Hunter int start(void **data, void *ctx)
16382b0a103SAdrian Hunter {
16482b0a103SAdrian Hunter int dlargc;
16582b0a103SAdrian Hunter char **dlargv;
16682b0a103SAdrian Hunter struct filter_data *d;
16782b0a103SAdrian Hunter static bool called;
16882b0a103SAdrian Hunter
16982b0a103SAdrian Hunter verbose = 1;
17082b0a103SAdrian Hunter
17182b0a103SAdrian Hunter CHECK(!filt_dat && !called);
17282b0a103SAdrian Hunter called = true;
17382b0a103SAdrian Hunter
17482b0a103SAdrian Hunter d = calloc(1, sizeof(*d));
17582b0a103SAdrian Hunter if (!d)
17682b0a103SAdrian Hunter test_fail("Failed to allocate memory");
17782b0a103SAdrian Hunter filt_dat = d;
17882b0a103SAdrian Hunter *data = d;
17982b0a103SAdrian Hunter
18082b0a103SAdrian Hunter dlargv = perf_dlfilter_fns.args(ctx, &dlargc);
18182b0a103SAdrian Hunter
18282b0a103SAdrian Hunter CHECK(dlargc == 6);
18382b0a103SAdrian Hunter CHECK(!strcmp(dlargv[0], "first"));
18482b0a103SAdrian Hunter verbose = strtol(dlargv[1], NULL, 0);
18582b0a103SAdrian Hunter d->ip = strtoull(dlargv[2], NULL, 0);
18682b0a103SAdrian Hunter d->addr = strtoull(dlargv[3], NULL, 0);
18782b0a103SAdrian Hunter d->do_early = strtol(dlargv[4], NULL, 0);
18882b0a103SAdrian Hunter CHECK(!strcmp(dlargv[5], "last"));
18982b0a103SAdrian Hunter
19082b0a103SAdrian Hunter pr_debug("%s API\n", __func__);
19182b0a103SAdrian Hunter
19282b0a103SAdrian Hunter return 0;
19382b0a103SAdrian Hunter }
19482b0a103SAdrian Hunter
19582b0a103SAdrian Hunter #define CHECK_SAMPLE(x) do { \
19682b0a103SAdrian Hunter if (sample->x != expected.x) \
19782b0a103SAdrian Hunter return test_fail("'" #x "' not expected value\n"); \
19882b0a103SAdrian Hunter } while (0)
19982b0a103SAdrian Hunter
check_sample(struct filter_data * d,const struct perf_dlfilter_sample * sample)20082b0a103SAdrian Hunter static int check_sample(struct filter_data *d, const struct perf_dlfilter_sample *sample)
20182b0a103SAdrian Hunter {
20282b0a103SAdrian Hunter struct perf_dlfilter_sample expected = {
20382b0a103SAdrian Hunter .ip = d->ip,
20482b0a103SAdrian Hunter .pid = 12345,
20582b0a103SAdrian Hunter .tid = 12346,
20682b0a103SAdrian Hunter .time = 1234567890,
20782b0a103SAdrian Hunter .addr = d->addr,
20882b0a103SAdrian Hunter .id = 99,
20982b0a103SAdrian Hunter .stream_id = 101,
21082b0a103SAdrian Hunter .period = 543212345,
21182b0a103SAdrian Hunter .cpu = 31,
21282b0a103SAdrian Hunter .cpumode = PERF_RECORD_MISC_USER,
21382b0a103SAdrian Hunter .addr_correlates_sym = 1,
21482b0a103SAdrian Hunter .misc = PERF_RECORD_MISC_USER,
21582b0a103SAdrian Hunter };
21682b0a103SAdrian Hunter
21782b0a103SAdrian Hunter CHECK(sample->size >= sizeof(struct perf_dlfilter_sample));
21882b0a103SAdrian Hunter
21982b0a103SAdrian Hunter CHECK_SAMPLE(ip);
22082b0a103SAdrian Hunter CHECK_SAMPLE(pid);
22182b0a103SAdrian Hunter CHECK_SAMPLE(tid);
22282b0a103SAdrian Hunter CHECK_SAMPLE(time);
22382b0a103SAdrian Hunter CHECK_SAMPLE(addr);
22482b0a103SAdrian Hunter CHECK_SAMPLE(id);
22582b0a103SAdrian Hunter CHECK_SAMPLE(stream_id);
22682b0a103SAdrian Hunter CHECK_SAMPLE(period);
22782b0a103SAdrian Hunter CHECK_SAMPLE(cpu);
22882b0a103SAdrian Hunter CHECK_SAMPLE(cpumode);
22982b0a103SAdrian Hunter CHECK_SAMPLE(addr_correlates_sym);
23082b0a103SAdrian Hunter CHECK_SAMPLE(misc);
23182b0a103SAdrian Hunter
23282b0a103SAdrian Hunter CHECK(!sample->raw_data);
23382b0a103SAdrian Hunter CHECK_SAMPLE(brstack_nr);
23482b0a103SAdrian Hunter CHECK(!sample->brstack);
23582b0a103SAdrian Hunter CHECK_SAMPLE(raw_callchain_nr);
23682b0a103SAdrian Hunter CHECK(!sample->raw_callchain);
23782b0a103SAdrian Hunter
23882b0a103SAdrian Hunter #define EVENT_NAME "branches:"
23982b0a103SAdrian Hunter CHECK(!strncmp(sample->event, EVENT_NAME, strlen(EVENT_NAME)));
24082b0a103SAdrian Hunter
24182b0a103SAdrian Hunter return 0;
24282b0a103SAdrian Hunter }
24382b0a103SAdrian Hunter
check_al(void * ctx)24482b0a103SAdrian Hunter static int check_al(void *ctx)
24582b0a103SAdrian Hunter {
24682b0a103SAdrian Hunter const struct perf_dlfilter_al *al;
24782b0a103SAdrian Hunter
24882b0a103SAdrian Hunter al = perf_dlfilter_fns.resolve_ip(ctx);
24982b0a103SAdrian Hunter if (!al)
25082b0a103SAdrian Hunter return test_fail("resolve_ip() failed");
25182b0a103SAdrian Hunter
25282b0a103SAdrian Hunter CHECK(al->sym && !strcmp("foo", al->sym));
25382b0a103SAdrian Hunter CHECK(!al->symoff);
25482b0a103SAdrian Hunter
25582b0a103SAdrian Hunter return 0;
25682b0a103SAdrian Hunter }
25782b0a103SAdrian Hunter
check_addr_al(void * ctx)25882b0a103SAdrian Hunter static int check_addr_al(void *ctx)
25982b0a103SAdrian Hunter {
26082b0a103SAdrian Hunter const struct perf_dlfilter_al *addr_al;
26182b0a103SAdrian Hunter
26282b0a103SAdrian Hunter addr_al = perf_dlfilter_fns.resolve_addr(ctx);
26382b0a103SAdrian Hunter if (!addr_al)
26482b0a103SAdrian Hunter return test_fail("resolve_addr() failed");
26582b0a103SAdrian Hunter
26682b0a103SAdrian Hunter CHECK(addr_al->sym && !strcmp("bar", addr_al->sym));
26782b0a103SAdrian Hunter CHECK(!addr_al->symoff);
26882b0a103SAdrian Hunter
26982b0a103SAdrian Hunter return 0;
27082b0a103SAdrian Hunter }
27182b0a103SAdrian Hunter
check_address_al(void * ctx,const struct perf_dlfilter_sample * sample)27282b0a103SAdrian Hunter static int check_address_al(void *ctx, const struct perf_dlfilter_sample *sample)
27382b0a103SAdrian Hunter {
27482b0a103SAdrian Hunter struct perf_dlfilter_al address_al;
27582b0a103SAdrian Hunter const struct perf_dlfilter_al *al;
27682b0a103SAdrian Hunter
27782b0a103SAdrian Hunter al = perf_dlfilter_fns.resolve_ip(ctx);
27882b0a103SAdrian Hunter if (!al)
27982b0a103SAdrian Hunter return test_fail("resolve_ip() failed");
28082b0a103SAdrian Hunter
28182b0a103SAdrian Hunter address_al.size = sizeof(address_al);
28282b0a103SAdrian Hunter if (perf_dlfilter_fns.resolve_address(ctx, sample->ip, &address_al))
28382b0a103SAdrian Hunter return test_fail("resolve_address() failed");
28482b0a103SAdrian Hunter
28582b0a103SAdrian Hunter CHECK(address_al.sym && al->sym);
28682b0a103SAdrian Hunter CHECK(!strcmp(address_al.sym, al->sym));
28782b0a103SAdrian Hunter CHECK(address_al.addr == al->addr);
28882b0a103SAdrian Hunter CHECK(address_al.sym_start == al->sym_start);
28982b0a103SAdrian Hunter CHECK(address_al.sym_end == al->sym_end);
29082b0a103SAdrian Hunter CHECK(address_al.dso && al->dso);
29182b0a103SAdrian Hunter CHECK(!strcmp(address_al.dso, al->dso));
29282b0a103SAdrian Hunter
29382b0a103SAdrian Hunter /* al_cleanup() is v2 API so may not be present */
29482b0a103SAdrian Hunter if (perf_dlfilter_fns.al_cleanup)
29582b0a103SAdrian Hunter perf_dlfilter_fns.al_cleanup(ctx, &address_al);
29682b0a103SAdrian Hunter
29782b0a103SAdrian Hunter return 0;
29882b0a103SAdrian Hunter }
29982b0a103SAdrian Hunter
check_attr(void * ctx)30082b0a103SAdrian Hunter static int check_attr(void *ctx)
30182b0a103SAdrian Hunter {
30282b0a103SAdrian Hunter struct perf_event_attr *attr = perf_dlfilter_fns.attr(ctx);
30382b0a103SAdrian Hunter
30482b0a103SAdrian Hunter CHECK(attr);
30582b0a103SAdrian Hunter CHECK(attr->type == PERF_TYPE_HARDWARE);
30682b0a103SAdrian Hunter CHECK(attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
30782b0a103SAdrian Hunter
30882b0a103SAdrian Hunter return 0;
30982b0a103SAdrian Hunter }
31082b0a103SAdrian Hunter
check_object_code(void * ctx,const struct perf_dlfilter_sample * sample)311*f38f5473SAdrian Hunter static int check_object_code(void *ctx, const struct perf_dlfilter_sample *sample)
312*f38f5473SAdrian Hunter {
313*f38f5473SAdrian Hunter __u8 buf[15];
314*f38f5473SAdrian Hunter
315*f38f5473SAdrian Hunter CHECK(perf_dlfilter_fns.object_code(ctx, sample->ip, buf, sizeof(buf)) > 0);
316*f38f5473SAdrian Hunter
317*f38f5473SAdrian Hunter return 0;
318*f38f5473SAdrian Hunter }
319*f38f5473SAdrian Hunter
do_checks(void * data,const struct perf_dlfilter_sample * sample,void * ctx,bool early)32082b0a103SAdrian Hunter static int do_checks(void *data, const struct perf_dlfilter_sample *sample, void *ctx, bool early)
32182b0a103SAdrian Hunter {
32282b0a103SAdrian Hunter struct filter_data *d = data;
32382b0a103SAdrian Hunter
32482b0a103SAdrian Hunter CHECK(data && filt_dat == data);
32582b0a103SAdrian Hunter
32682b0a103SAdrian Hunter if (early) {
32782b0a103SAdrian Hunter CHECK(!d->early_filter_cnt);
32882b0a103SAdrian Hunter d->early_filter_cnt += 1;
32982b0a103SAdrian Hunter } else {
33082b0a103SAdrian Hunter CHECK(!d->filter_cnt);
33182b0a103SAdrian Hunter CHECK(d->early_filter_cnt);
33282b0a103SAdrian Hunter CHECK(d->do_early != 2);
33382b0a103SAdrian Hunter d->filter_cnt += 1;
33482b0a103SAdrian Hunter }
33582b0a103SAdrian Hunter
33682b0a103SAdrian Hunter if (check_sample(data, sample))
33782b0a103SAdrian Hunter return -1;
33882b0a103SAdrian Hunter
33982b0a103SAdrian Hunter if (check_attr(ctx))
34082b0a103SAdrian Hunter return -1;
34182b0a103SAdrian Hunter
34282b0a103SAdrian Hunter if (early && !d->do_early)
34382b0a103SAdrian Hunter return 0;
34482b0a103SAdrian Hunter
345*f38f5473SAdrian Hunter if (check_al(ctx) || check_addr_al(ctx) || check_address_al(ctx, sample) ||
346*f38f5473SAdrian Hunter check_object_code(ctx, sample))
34782b0a103SAdrian Hunter return -1;
34882b0a103SAdrian Hunter
34982b0a103SAdrian Hunter if (early)
35082b0a103SAdrian Hunter return d->do_early == 2;
35182b0a103SAdrian Hunter
35282b0a103SAdrian Hunter return 1;
35382b0a103SAdrian Hunter }
35482b0a103SAdrian Hunter
filter_event_early(void * data,const struct perf_dlfilter_sample * sample,void * ctx)35582b0a103SAdrian Hunter int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
35682b0a103SAdrian Hunter {
35782b0a103SAdrian Hunter pr_debug("%s API\n", __func__);
35882b0a103SAdrian Hunter
35982b0a103SAdrian Hunter return do_checks(data, sample, ctx, true);
36082b0a103SAdrian Hunter }
36182b0a103SAdrian Hunter
filter_event(void * data,const struct perf_dlfilter_sample * sample,void * ctx)36282b0a103SAdrian Hunter int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
36382b0a103SAdrian Hunter {
36482b0a103SAdrian Hunter pr_debug("%s API\n", __func__);
36582b0a103SAdrian Hunter
36682b0a103SAdrian Hunter return do_checks(data, sample, ctx, false);
36782b0a103SAdrian Hunter }
36882b0a103SAdrian Hunter
stop(void * data,void * ctx)36982b0a103SAdrian Hunter int stop(void *data, void *ctx)
37082b0a103SAdrian Hunter {
37182b0a103SAdrian Hunter static bool called;
37282b0a103SAdrian Hunter
37382b0a103SAdrian Hunter pr_debug("%s API\n", __func__);
37482b0a103SAdrian Hunter
37582b0a103SAdrian Hunter CHECK(data && filt_dat == data && !called);
37682b0a103SAdrian Hunter called = true;
37782b0a103SAdrian Hunter
37882b0a103SAdrian Hunter free(data);
37982b0a103SAdrian Hunter filt_dat = NULL;
38082b0a103SAdrian Hunter return 0;
38182b0a103SAdrian Hunter }
38282b0a103SAdrian Hunter
filter_description(const char ** long_description)38382b0a103SAdrian Hunter const char *filter_description(const char **long_description)
38482b0a103SAdrian Hunter {
38582b0a103SAdrian Hunter *long_description = "Filter used by the 'dlfilter C API' perf test";
38682b0a103SAdrian Hunter return "dlfilter to test v2 C API";
38782b0a103SAdrian Hunter }
388