xref: /openbmc/linux/tools/perf/tests/dlfilter-test.c (revision 82b0a103)
19f9c9a8dSAdrian Hunter // SPDX-License-Identifier: GPL-2.0
29f9c9a8dSAdrian Hunter /*
39f9c9a8dSAdrian Hunter  * Test dlfilter C API. A perf.data file is synthesized and then processed
4*82b0a103SAdrian Hunter  * by perf script with dlfilters named dlfilter-test-api-v*.so. Also a C file
59f9c9a8dSAdrian Hunter  * is compiled to provide a dso to match the synthesized perf.data file.
69f9c9a8dSAdrian Hunter  */
79f9c9a8dSAdrian Hunter 
89f9c9a8dSAdrian Hunter #include <linux/compiler.h>
99f9c9a8dSAdrian Hunter #include <linux/kernel.h>
109f9c9a8dSAdrian Hunter #include <linux/string.h>
119f9c9a8dSAdrian Hunter #include <linux/perf_event.h>
129f9c9a8dSAdrian Hunter #include <internal/lib.h>
139f9c9a8dSAdrian Hunter #include <subcmd/exec-cmd.h>
149f9c9a8dSAdrian Hunter #include <sys/types.h>
159f9c9a8dSAdrian Hunter #include <sys/stat.h>
169f9c9a8dSAdrian Hunter #include <fcntl.h>
179f9c9a8dSAdrian Hunter #include <stdlib.h>
189f9c9a8dSAdrian Hunter #include <unistd.h>
199f9c9a8dSAdrian Hunter #include <inttypes.h>
209f9c9a8dSAdrian Hunter #include <libgen.h>
219f9c9a8dSAdrian Hunter #include <string.h>
229f9c9a8dSAdrian Hunter #include <errno.h>
239f9c9a8dSAdrian Hunter #include "debug.h"
249f9c9a8dSAdrian Hunter #include "tool.h"
259f9c9a8dSAdrian Hunter #include "event.h"
269f9c9a8dSAdrian Hunter #include "header.h"
279f9c9a8dSAdrian Hunter #include "machine.h"
289f9c9a8dSAdrian Hunter #include "dso.h"
299f9c9a8dSAdrian Hunter #include "map.h"
309f9c9a8dSAdrian Hunter #include "symbol.h"
319f9c9a8dSAdrian Hunter #include "synthetic-events.h"
329f9c9a8dSAdrian Hunter #include "util.h"
339f9c9a8dSAdrian Hunter #include "archinsn.h"
349f9c9a8dSAdrian Hunter #include "dlfilter.h"
359f9c9a8dSAdrian Hunter #include "tests.h"
369823147dSArnaldo Carvalho de Melo #include "util/sample.h"
379f9c9a8dSAdrian Hunter 
389f9c9a8dSAdrian Hunter #define MAP_START 0x400000
399f9c9a8dSAdrian Hunter 
40*82b0a103SAdrian Hunter #define DLFILTER_TEST_NAME_MAX 128
41*82b0a103SAdrian Hunter 
429f9c9a8dSAdrian Hunter struct test_data {
439f9c9a8dSAdrian Hunter 	struct perf_tool tool;
449f9c9a8dSAdrian Hunter 	struct machine *machine;
459f9c9a8dSAdrian Hunter 	int fd;
469f9c9a8dSAdrian Hunter 	u64 foo;
479f9c9a8dSAdrian Hunter 	u64 bar;
489f9c9a8dSAdrian Hunter 	u64 ip;
499f9c9a8dSAdrian Hunter 	u64 addr;
50*82b0a103SAdrian Hunter 	char name[DLFILTER_TEST_NAME_MAX];
51*82b0a103SAdrian Hunter 	char desc[DLFILTER_TEST_NAME_MAX];
529f9c9a8dSAdrian Hunter 	char perf[PATH_MAX];
539f9c9a8dSAdrian Hunter 	char perf_data_file_name[PATH_MAX];
549f9c9a8dSAdrian Hunter 	char c_file_name[PATH_MAX];
559f9c9a8dSAdrian Hunter 	char prog_file_name[PATH_MAX];
569f9c9a8dSAdrian Hunter 	char dlfilters[PATH_MAX];
579f9c9a8dSAdrian Hunter };
589f9c9a8dSAdrian Hunter 
test_result(const char * msg,int ret)599f9c9a8dSAdrian Hunter static int test_result(const char *msg, int ret)
609f9c9a8dSAdrian Hunter {
619f9c9a8dSAdrian Hunter 	pr_debug("%s\n", msg);
629f9c9a8dSAdrian Hunter 	return ret;
639f9c9a8dSAdrian Hunter }
649f9c9a8dSAdrian Hunter 
process(struct perf_tool * tool,union perf_event * event,struct perf_sample * sample __maybe_unused,struct machine * machine __maybe_unused)659f9c9a8dSAdrian Hunter static int process(struct perf_tool *tool, union perf_event *event,
669f9c9a8dSAdrian Hunter 		   struct perf_sample *sample __maybe_unused,
679f9c9a8dSAdrian Hunter 		   struct machine *machine __maybe_unused)
689f9c9a8dSAdrian Hunter {
699f9c9a8dSAdrian Hunter 	struct test_data *td = container_of(tool, struct test_data, tool);
709f9c9a8dSAdrian Hunter 	int fd = td->fd;
719f9c9a8dSAdrian Hunter 
729f9c9a8dSAdrian Hunter 	if (writen(fd, event, event->header.size) != event->header.size)
739f9c9a8dSAdrian Hunter 		return -1;
749f9c9a8dSAdrian Hunter 
759f9c9a8dSAdrian Hunter 	return 0;
769f9c9a8dSAdrian Hunter }
779f9c9a8dSAdrian Hunter 
789f9c9a8dSAdrian Hunter #define MAXCMD 4096
799f9c9a8dSAdrian Hunter #define REDIRECT_TO_DEV_NULL " >/dev/null 2>&1"
809f9c9a8dSAdrian Hunter 
system_cmd(const char * fmt,...)819f9c9a8dSAdrian Hunter static __printf(1, 2) int system_cmd(const char *fmt, ...)
829f9c9a8dSAdrian Hunter {
839f9c9a8dSAdrian Hunter 	char cmd[MAXCMD + sizeof(REDIRECT_TO_DEV_NULL)];
849f9c9a8dSAdrian Hunter 	int ret;
859f9c9a8dSAdrian Hunter 
869f9c9a8dSAdrian Hunter 	va_list args;
879f9c9a8dSAdrian Hunter 
889f9c9a8dSAdrian Hunter 	va_start(args, fmt);
899f9c9a8dSAdrian Hunter 	ret = vsnprintf(cmd, MAXCMD, fmt, args);
909f9c9a8dSAdrian Hunter 	va_end(args);
919f9c9a8dSAdrian Hunter 
929f9c9a8dSAdrian Hunter 	if (ret <= 0 || ret >= MAXCMD)
939f9c9a8dSAdrian Hunter 		return -1;
949f9c9a8dSAdrian Hunter 
957c0a6144SYang Jihong 	if (verbose <= 0)
969f9c9a8dSAdrian Hunter 		strcat(cmd, REDIRECT_TO_DEV_NULL);
979f9c9a8dSAdrian Hunter 
989f9c9a8dSAdrian Hunter 	pr_debug("Command: %s\n", cmd);
999f9c9a8dSAdrian Hunter 	ret = system(cmd);
1009f9c9a8dSAdrian Hunter 	if (ret)
1019f9c9a8dSAdrian Hunter 		pr_debug("Failed with return value %d\n", ret);
1029f9c9a8dSAdrian Hunter 
1039f9c9a8dSAdrian Hunter 	return ret;
1049f9c9a8dSAdrian Hunter }
1059f9c9a8dSAdrian Hunter 
have_gcc(void)1069f9c9a8dSAdrian Hunter static bool have_gcc(void)
1079f9c9a8dSAdrian Hunter {
1089f9c9a8dSAdrian Hunter 	pr_debug("Checking for gcc\n");
1099f9c9a8dSAdrian Hunter 	return !system_cmd("gcc --version");
1109f9c9a8dSAdrian Hunter }
1119f9c9a8dSAdrian Hunter 
write_attr(struct test_data * td,u64 sample_type,u64 * id)1129f9c9a8dSAdrian Hunter static int write_attr(struct test_data *td, u64 sample_type, u64 *id)
1139f9c9a8dSAdrian Hunter {
1149f9c9a8dSAdrian Hunter 	struct perf_event_attr attr = {
1159f9c9a8dSAdrian Hunter 		.size = sizeof(attr),
1169f9c9a8dSAdrian Hunter 		.type = PERF_TYPE_HARDWARE,
1179f9c9a8dSAdrian Hunter 		.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS,
1189f9c9a8dSAdrian Hunter 		.sample_type = sample_type,
1199f9c9a8dSAdrian Hunter 		.sample_period = 1,
1209f9c9a8dSAdrian Hunter 	};
1219f9c9a8dSAdrian Hunter 
1229f9c9a8dSAdrian Hunter 	return perf_event__synthesize_attr(&td->tool, &attr, 1, id, process);
1239f9c9a8dSAdrian Hunter }
1249f9c9a8dSAdrian Hunter 
write_comm(int fd,pid_t pid,pid_t tid,const char * comm_str)1259f9c9a8dSAdrian Hunter static int write_comm(int fd, pid_t pid, pid_t tid, const char *comm_str)
1269f9c9a8dSAdrian Hunter {
1279f9c9a8dSAdrian Hunter 	struct perf_record_comm comm;
1289f9c9a8dSAdrian Hunter 	ssize_t sz = sizeof(comm);
1299f9c9a8dSAdrian Hunter 
1309f9c9a8dSAdrian Hunter 	comm.header.type = PERF_RECORD_COMM;
1319f9c9a8dSAdrian Hunter 	comm.header.misc = PERF_RECORD_MISC_USER;
1329f9c9a8dSAdrian Hunter 	comm.header.size = sz;
1339f9c9a8dSAdrian Hunter 
1349f9c9a8dSAdrian Hunter 	comm.pid = pid;
1359f9c9a8dSAdrian Hunter 	comm.tid = tid;
1369f9c9a8dSAdrian Hunter 	strncpy(comm.comm, comm_str, 16);
1379f9c9a8dSAdrian Hunter 
1389f9c9a8dSAdrian Hunter 	if (writen(fd, &comm, sz) != sz) {
1399f9c9a8dSAdrian Hunter 		pr_debug("%s failed\n", __func__);
1409f9c9a8dSAdrian Hunter 		return -1;
1419f9c9a8dSAdrian Hunter 	}
1429f9c9a8dSAdrian Hunter 
1439f9c9a8dSAdrian Hunter 	return 0;
1449f9c9a8dSAdrian Hunter }
1459f9c9a8dSAdrian Hunter 
write_mmap(int fd,pid_t pid,pid_t tid,u64 start,u64 len,u64 pgoff,const char * filename)1469f9c9a8dSAdrian Hunter static int write_mmap(int fd, pid_t pid, pid_t tid, u64 start, u64 len, u64 pgoff,
1479f9c9a8dSAdrian Hunter 		      const char *filename)
1489f9c9a8dSAdrian Hunter {
1499f9c9a8dSAdrian Hunter 	char buf[PERF_SAMPLE_MAX_SIZE];
1509f9c9a8dSAdrian Hunter 	struct perf_record_mmap *mmap = (struct perf_record_mmap *)buf;
1519f9c9a8dSAdrian Hunter 	size_t fsz = roundup(strlen(filename) + 1, 8);
1529f9c9a8dSAdrian Hunter 	ssize_t sz = sizeof(*mmap) - sizeof(mmap->filename) + fsz;
1539f9c9a8dSAdrian Hunter 
1549f9c9a8dSAdrian Hunter 	mmap->header.type = PERF_RECORD_MMAP;
1559f9c9a8dSAdrian Hunter 	mmap->header.misc = PERF_RECORD_MISC_USER;
1569f9c9a8dSAdrian Hunter 	mmap->header.size = sz;
1579f9c9a8dSAdrian Hunter 
1589f9c9a8dSAdrian Hunter 	mmap->pid   = pid;
1599f9c9a8dSAdrian Hunter 	mmap->tid   = tid;
1609f9c9a8dSAdrian Hunter 	mmap->start = start;
1619f9c9a8dSAdrian Hunter 	mmap->len   = len;
1629f9c9a8dSAdrian Hunter 	mmap->pgoff = pgoff;
1639f9c9a8dSAdrian Hunter 	strncpy(mmap->filename, filename, sizeof(mmap->filename));
1649f9c9a8dSAdrian Hunter 
1659f9c9a8dSAdrian Hunter 	if (writen(fd, mmap, sz) != sz) {
1669f9c9a8dSAdrian Hunter 		pr_debug("%s failed\n", __func__);
1679f9c9a8dSAdrian Hunter 		return -1;
1689f9c9a8dSAdrian Hunter 	}
1699f9c9a8dSAdrian Hunter 
1709f9c9a8dSAdrian Hunter 	return 0;
1719f9c9a8dSAdrian Hunter }
1729f9c9a8dSAdrian Hunter 
write_sample(struct test_data * td,u64 sample_type,u64 id,pid_t pid,pid_t tid)1739f9c9a8dSAdrian Hunter static int write_sample(struct test_data *td, u64 sample_type, u64 id, pid_t pid, pid_t tid)
1749f9c9a8dSAdrian Hunter {
1759f9c9a8dSAdrian Hunter 	char buf[PERF_SAMPLE_MAX_SIZE];
1769f9c9a8dSAdrian Hunter 	union perf_event *event = (union perf_event *)buf;
1779f9c9a8dSAdrian Hunter 	struct perf_sample sample = {
1789f9c9a8dSAdrian Hunter 		.ip		= td->ip,
1799f9c9a8dSAdrian Hunter 		.addr		= td->addr,
1809f9c9a8dSAdrian Hunter 		.id		= id,
1819f9c9a8dSAdrian Hunter 		.time		= 1234567890,
1829f9c9a8dSAdrian Hunter 		.cpu		= 31,
1839f9c9a8dSAdrian Hunter 		.pid		= pid,
1849f9c9a8dSAdrian Hunter 		.tid		= tid,
1859f9c9a8dSAdrian Hunter 		.period		= 543212345,
1869f9c9a8dSAdrian Hunter 		.stream_id	= 101,
1879f9c9a8dSAdrian Hunter 	};
1889f9c9a8dSAdrian Hunter 	int err;
1899f9c9a8dSAdrian Hunter 
1909f9c9a8dSAdrian Hunter 	event->header.type = PERF_RECORD_SAMPLE;
1919f9c9a8dSAdrian Hunter 	event->header.misc = PERF_RECORD_MISC_USER;
1929f9c9a8dSAdrian Hunter 	event->header.size = perf_event__sample_event_size(&sample, sample_type, 0);
1939f9c9a8dSAdrian Hunter 	err = perf_event__synthesize_sample(event, sample_type, 0, &sample);
1949f9c9a8dSAdrian Hunter 	if (err)
1959f9c9a8dSAdrian Hunter 		return test_result("perf_event__synthesize_sample() failed", TEST_FAIL);
1969f9c9a8dSAdrian Hunter 
1979f9c9a8dSAdrian Hunter 	err = process(&td->tool, event, &sample, td->machine);
1989f9c9a8dSAdrian Hunter 	if (err)
1999f9c9a8dSAdrian Hunter 		return test_result("Failed to write sample", TEST_FAIL);
2009f9c9a8dSAdrian Hunter 
2019f9c9a8dSAdrian Hunter 	return TEST_OK;
2029f9c9a8dSAdrian Hunter }
2039f9c9a8dSAdrian Hunter 
close_fd(int fd)2049f9c9a8dSAdrian Hunter static void close_fd(int fd)
2059f9c9a8dSAdrian Hunter {
2069f9c9a8dSAdrian Hunter 	if (fd >= 0)
2079f9c9a8dSAdrian Hunter 		close(fd);
2089f9c9a8dSAdrian Hunter }
2099f9c9a8dSAdrian Hunter 
2109f9c9a8dSAdrian Hunter static const char *prog = "int bar(){};int foo(){bar();};int main(){foo();return 0;}";
2119f9c9a8dSAdrian Hunter 
write_prog(char * file_name)2129f9c9a8dSAdrian Hunter static int write_prog(char *file_name)
2139f9c9a8dSAdrian Hunter {
2149f9c9a8dSAdrian Hunter 	int fd = creat(file_name, 0644);
2159f9c9a8dSAdrian Hunter 	ssize_t n = strlen(prog);
2169f9c9a8dSAdrian Hunter 	bool err = fd < 0 || writen(fd, prog, n) != n;
2179f9c9a8dSAdrian Hunter 
2189f9c9a8dSAdrian Hunter 	close_fd(fd);
2199f9c9a8dSAdrian Hunter 	return err ? -1 : 0;
2209f9c9a8dSAdrian Hunter }
2219f9c9a8dSAdrian Hunter 
get_dlfilters_path(const char * name,char * buf,size_t sz)222*82b0a103SAdrian Hunter static int get_dlfilters_path(const char *name, char *buf, size_t sz)
2239f9c9a8dSAdrian Hunter {
2249f9c9a8dSAdrian Hunter 	char perf[PATH_MAX];
2259f9c9a8dSAdrian Hunter 	char path[PATH_MAX];
2269f9c9a8dSAdrian Hunter 	char *perf_path;
2279f9c9a8dSAdrian Hunter 	char *exec_path;
2289f9c9a8dSAdrian Hunter 
2299f9c9a8dSAdrian Hunter 	perf_exe(perf, sizeof(perf));
2309f9c9a8dSAdrian Hunter 	perf_path = dirname(perf);
231*82b0a103SAdrian Hunter 	snprintf(path, sizeof(path), "%s/dlfilters/%s", perf_path, name);
2329f9c9a8dSAdrian Hunter 	if (access(path, R_OK)) {
2339f9c9a8dSAdrian Hunter 		exec_path = get_argv_exec_path();
2349f9c9a8dSAdrian Hunter 		if (!exec_path)
2359f9c9a8dSAdrian Hunter 			return -1;
236*82b0a103SAdrian Hunter 		snprintf(path, sizeof(path), "%s/dlfilters/%s", exec_path, name);
2379f9c9a8dSAdrian Hunter 		free(exec_path);
2389f9c9a8dSAdrian Hunter 		if (access(path, R_OK))
2399f9c9a8dSAdrian Hunter 			return -1;
2409f9c9a8dSAdrian Hunter 	}
2419f9c9a8dSAdrian Hunter 	strlcpy(buf, dirname(path), sz);
2429f9c9a8dSAdrian Hunter 	return 0;
2439f9c9a8dSAdrian Hunter }
2449f9c9a8dSAdrian Hunter 
check_filter_desc(struct test_data * td)2459f9c9a8dSAdrian Hunter static int check_filter_desc(struct test_data *td)
2469f9c9a8dSAdrian Hunter {
2476ca822e5SRiccardo Mancini 	char *long_desc = NULL;
2486ca822e5SRiccardo Mancini 	char *desc = NULL;
2496ca822e5SRiccardo Mancini 	int ret;
2509f9c9a8dSAdrian Hunter 
251*82b0a103SAdrian Hunter 	if (get_filter_desc(td->dlfilters, td->name, &desc, &long_desc) &&
2529f9c9a8dSAdrian Hunter 	    long_desc && !strcmp(long_desc, "Filter used by the 'dlfilter C API' perf test") &&
253*82b0a103SAdrian Hunter 	    desc && !strcmp(desc, td->desc))
2546ca822e5SRiccardo Mancini 		ret = 0;
2556ca822e5SRiccardo Mancini 	else
2566ca822e5SRiccardo Mancini 		ret = -1;
2579f9c9a8dSAdrian Hunter 
2586ca822e5SRiccardo Mancini 	free(desc);
2596ca822e5SRiccardo Mancini 	free(long_desc);
2606ca822e5SRiccardo Mancini 	return ret;
2619f9c9a8dSAdrian Hunter }
2629f9c9a8dSAdrian Hunter 
get_ip_addr(struct test_data * td)2639f9c9a8dSAdrian Hunter static int get_ip_addr(struct test_data *td)
2649f9c9a8dSAdrian Hunter {
2659f9c9a8dSAdrian Hunter 	struct map *map;
2669f9c9a8dSAdrian Hunter 	struct symbol *sym;
2679f9c9a8dSAdrian Hunter 
2689f9c9a8dSAdrian Hunter 	map = dso__new_map(td->prog_file_name);
2699f9c9a8dSAdrian Hunter 	if (!map)
2709f9c9a8dSAdrian Hunter 		return -1;
2719f9c9a8dSAdrian Hunter 
2729f9c9a8dSAdrian Hunter 	sym = map__find_symbol_by_name(map, "foo");
2739f9c9a8dSAdrian Hunter 	if (sym)
2749f9c9a8dSAdrian Hunter 		td->foo = sym->start;
2759f9c9a8dSAdrian Hunter 
2769f9c9a8dSAdrian Hunter 	sym = map__find_symbol_by_name(map, "bar");
2779f9c9a8dSAdrian Hunter 	if (sym)
2789f9c9a8dSAdrian Hunter 		td->bar = sym->start;
2799f9c9a8dSAdrian Hunter 
2809f9c9a8dSAdrian Hunter 	map__put(map);
2819f9c9a8dSAdrian Hunter 
2829f9c9a8dSAdrian Hunter 	td->ip = MAP_START + td->foo;
2839f9c9a8dSAdrian Hunter 	td->addr = MAP_START + td->bar;
2849f9c9a8dSAdrian Hunter 
2859f9c9a8dSAdrian Hunter 	return td->foo && td->bar ? 0 : -1;
2869f9c9a8dSAdrian Hunter }
2879f9c9a8dSAdrian Hunter 
do_run_perf_script(struct test_data * td,int do_early)2889f9c9a8dSAdrian Hunter static int do_run_perf_script(struct test_data *td, int do_early)
2899f9c9a8dSAdrian Hunter {
2909f9c9a8dSAdrian Hunter 	return system_cmd("%s script -i %s "
291*82b0a103SAdrian Hunter 			  "--dlfilter %s/%s "
2929f9c9a8dSAdrian Hunter 			  "--dlarg first "
2939f9c9a8dSAdrian Hunter 			  "--dlarg %d "
2949f9c9a8dSAdrian Hunter 			  "--dlarg %" PRIu64 " "
2959f9c9a8dSAdrian Hunter 			  "--dlarg %" PRIu64 " "
2969f9c9a8dSAdrian Hunter 			  "--dlarg %d "
2979f9c9a8dSAdrian Hunter 			  "--dlarg last",
2989f9c9a8dSAdrian Hunter 			  td->perf, td->perf_data_file_name, td->dlfilters,
299*82b0a103SAdrian Hunter 			  td->name, verbose, td->ip, td->addr, do_early);
3009f9c9a8dSAdrian Hunter }
3019f9c9a8dSAdrian Hunter 
run_perf_script(struct test_data * td)3029f9c9a8dSAdrian Hunter static int run_perf_script(struct test_data *td)
3039f9c9a8dSAdrian Hunter {
3049f9c9a8dSAdrian Hunter 	int do_early;
3059f9c9a8dSAdrian Hunter 	int err;
3069f9c9a8dSAdrian Hunter 
3079f9c9a8dSAdrian Hunter 	for (do_early = 0; do_early < 3; do_early++) {
3089f9c9a8dSAdrian Hunter 		err = do_run_perf_script(td, do_early);
3099f9c9a8dSAdrian Hunter 		if (err)
3109f9c9a8dSAdrian Hunter 			return err;
3119f9c9a8dSAdrian Hunter 	}
3129f9c9a8dSAdrian Hunter 	return 0;
3139f9c9a8dSAdrian Hunter }
3149f9c9a8dSAdrian Hunter 
3159f9c9a8dSAdrian Hunter #define TEST_SAMPLE_TYPE (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
3169f9c9a8dSAdrian Hunter 			  PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_TIME | \
3179f9c9a8dSAdrian Hunter 			  PERF_SAMPLE_ADDR | PERF_SAMPLE_CPU | \
3189f9c9a8dSAdrian Hunter 			  PERF_SAMPLE_PERIOD | PERF_SAMPLE_STREAM_ID)
3199f9c9a8dSAdrian Hunter 
test__dlfilter_test(struct test_data * td)3209f9c9a8dSAdrian Hunter static int test__dlfilter_test(struct test_data *td)
3219f9c9a8dSAdrian Hunter {
3229f9c9a8dSAdrian Hunter 	u64 sample_type = TEST_SAMPLE_TYPE;
3239f9c9a8dSAdrian Hunter 	pid_t pid = 12345;
3249f9c9a8dSAdrian Hunter 	pid_t tid = 12346;
3259f9c9a8dSAdrian Hunter 	u64 id = 99;
3269f9c9a8dSAdrian Hunter 	int err;
3279f9c9a8dSAdrian Hunter 
328*82b0a103SAdrian Hunter 	if (get_dlfilters_path(td->name, td->dlfilters, PATH_MAX))
3299f9c9a8dSAdrian Hunter 		return test_result("dlfilters not found", TEST_SKIP);
3309f9c9a8dSAdrian Hunter 
3319f9c9a8dSAdrian Hunter 	if (check_filter_desc(td))
3329f9c9a8dSAdrian Hunter 		return test_result("Failed to get expected filter description", TEST_FAIL);
3339f9c9a8dSAdrian Hunter 
3349f9c9a8dSAdrian Hunter 	if (!have_gcc())
3359f9c9a8dSAdrian Hunter 		return test_result("gcc not found", TEST_SKIP);
3369f9c9a8dSAdrian Hunter 
3379f9c9a8dSAdrian Hunter 	pr_debug("dlfilters path: %s\n", td->dlfilters);
3389f9c9a8dSAdrian Hunter 
3399f9c9a8dSAdrian Hunter 	if (write_prog(td->c_file_name))
3409f9c9a8dSAdrian Hunter 		return test_result("Failed to write test C file", TEST_FAIL);
3419f9c9a8dSAdrian Hunter 
3429f9c9a8dSAdrian Hunter 	if (verbose > 1)
3439f9c9a8dSAdrian Hunter 		system_cmd("cat %s ; echo", td->c_file_name);
3449f9c9a8dSAdrian Hunter 
3459f9c9a8dSAdrian Hunter 	if (system_cmd("gcc -g -o %s %s", td->prog_file_name, td->c_file_name))
3469f9c9a8dSAdrian Hunter 		return TEST_FAIL;
3479f9c9a8dSAdrian Hunter 
3489f9c9a8dSAdrian Hunter 	if (verbose > 2)
3499f9c9a8dSAdrian Hunter 		system_cmd("objdump -x -dS %s", td->prog_file_name);
3509f9c9a8dSAdrian Hunter 
3519f9c9a8dSAdrian Hunter 	if (get_ip_addr(td))
3529f9c9a8dSAdrian Hunter 		return test_result("Failed to find program symbols", TEST_FAIL);
3539f9c9a8dSAdrian Hunter 
3549f9c9a8dSAdrian Hunter 	pr_debug("Creating new host machine structure\n");
3559f9c9a8dSAdrian Hunter 	td->machine = machine__new_host();
3569f9c9a8dSAdrian Hunter 	td->machine->env = &perf_env;
3579f9c9a8dSAdrian Hunter 
3589f9c9a8dSAdrian Hunter 	td->fd = creat(td->perf_data_file_name, 0644);
3599f9c9a8dSAdrian Hunter 	if (td->fd < 0)
3609f9c9a8dSAdrian Hunter 		return test_result("Failed to create test perf.data file", TEST_FAIL);
3619f9c9a8dSAdrian Hunter 
3629f9c9a8dSAdrian Hunter 	err = perf_header__write_pipe(td->fd);
3639f9c9a8dSAdrian Hunter 	if (err < 0)
3649f9c9a8dSAdrian Hunter 		return test_result("perf_header__write_pipe() failed", TEST_FAIL);
3659f9c9a8dSAdrian Hunter 
3669f9c9a8dSAdrian Hunter 	err = write_attr(td, sample_type, &id);
3679f9c9a8dSAdrian Hunter 	if (err)
3689f9c9a8dSAdrian Hunter 		return test_result("perf_event__synthesize_attr() failed", TEST_FAIL);
3699f9c9a8dSAdrian Hunter 
3709f9c9a8dSAdrian Hunter 	if (write_comm(td->fd, pid, tid, "test-prog"))
3719f9c9a8dSAdrian Hunter 		return TEST_FAIL;
3729f9c9a8dSAdrian Hunter 
3739f9c9a8dSAdrian Hunter 	if (write_mmap(td->fd, pid, tid, MAP_START, 0x10000, 0, td->prog_file_name))
3749f9c9a8dSAdrian Hunter 		return TEST_FAIL;
3759f9c9a8dSAdrian Hunter 
3769f9c9a8dSAdrian Hunter 	if (write_sample(td, sample_type, id, pid, tid) != TEST_OK)
3779f9c9a8dSAdrian Hunter 		return TEST_FAIL;
3789f9c9a8dSAdrian Hunter 
3799f9c9a8dSAdrian Hunter 	if (verbose > 1)
3809f9c9a8dSAdrian Hunter 		system_cmd("%s script -i %s -D", td->perf, td->perf_data_file_name);
3819f9c9a8dSAdrian Hunter 
3829f9c9a8dSAdrian Hunter 	err = run_perf_script(td);
3839f9c9a8dSAdrian Hunter 	if (err)
3849f9c9a8dSAdrian Hunter 		return TEST_FAIL;
3859f9c9a8dSAdrian Hunter 
3869f9c9a8dSAdrian Hunter 	return TEST_OK;
3879f9c9a8dSAdrian Hunter }
3889f9c9a8dSAdrian Hunter 
unlink_path(const char * path)3899f9c9a8dSAdrian Hunter static void unlink_path(const char *path)
3909f9c9a8dSAdrian Hunter {
3919f9c9a8dSAdrian Hunter 	if (*path)
3929f9c9a8dSAdrian Hunter 		unlink(path);
3939f9c9a8dSAdrian Hunter }
3949f9c9a8dSAdrian Hunter 
test_data__free(struct test_data * td)3959f9c9a8dSAdrian Hunter static void test_data__free(struct test_data *td)
3969f9c9a8dSAdrian Hunter {
3979f9c9a8dSAdrian Hunter 	machine__delete(td->machine);
3989f9c9a8dSAdrian Hunter 	close_fd(td->fd);
3999f9c9a8dSAdrian Hunter 	if (verbose <= 2) {
4009f9c9a8dSAdrian Hunter 		unlink_path(td->c_file_name);
4019f9c9a8dSAdrian Hunter 		unlink_path(td->prog_file_name);
4029f9c9a8dSAdrian Hunter 		unlink_path(td->perf_data_file_name);
4039f9c9a8dSAdrian Hunter 	}
4049f9c9a8dSAdrian Hunter }
4059f9c9a8dSAdrian Hunter 
test__dlfilter_ver(int ver)406*82b0a103SAdrian Hunter static int test__dlfilter_ver(int ver)
4079f9c9a8dSAdrian Hunter {
4089f9c9a8dSAdrian Hunter 	struct test_data td = {.fd = -1};
4099f9c9a8dSAdrian Hunter 	int pid = getpid();
4109f9c9a8dSAdrian Hunter 	int err;
4119f9c9a8dSAdrian Hunter 
412*82b0a103SAdrian Hunter 	pr_debug("\n-- Testing version %d API --\n", ver);
413*82b0a103SAdrian Hunter 
4149f9c9a8dSAdrian Hunter 	perf_exe(td.perf, sizeof(td.perf));
4159f9c9a8dSAdrian Hunter 
416*82b0a103SAdrian Hunter 	snprintf(td.name, sizeof(td.name), "dlfilter-test-api-v%d.so", ver);
417*82b0a103SAdrian Hunter 	snprintf(td.desc, sizeof(td.desc), "dlfilter to test v%d C API", ver);
4189f9c9a8dSAdrian Hunter 	snprintf(td.perf_data_file_name, PATH_MAX, "/tmp/dlfilter-test-%u-perf-data", pid);
4199f9c9a8dSAdrian Hunter 	snprintf(td.c_file_name, PATH_MAX, "/tmp/dlfilter-test-%u-prog.c", pid);
4209f9c9a8dSAdrian Hunter 	snprintf(td.prog_file_name, PATH_MAX, "/tmp/dlfilter-test-%u-prog", pid);
4219f9c9a8dSAdrian Hunter 
4229f9c9a8dSAdrian Hunter 	err = test__dlfilter_test(&td);
4239f9c9a8dSAdrian Hunter 	test_data__free(&td);
4249f9c9a8dSAdrian Hunter 	return err;
4259f9c9a8dSAdrian Hunter }
426d68f0365SIan Rogers 
test__dlfilter(struct test_suite * test __maybe_unused,int subtest __maybe_unused)427*82b0a103SAdrian Hunter static int test__dlfilter(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
428*82b0a103SAdrian Hunter {
429*82b0a103SAdrian Hunter 	int err = test__dlfilter_ver(0);
430*82b0a103SAdrian Hunter 
431*82b0a103SAdrian Hunter 	if (err)
432*82b0a103SAdrian Hunter 		return err;
433*82b0a103SAdrian Hunter 	/* No test for version 1 */
434*82b0a103SAdrian Hunter 	return test__dlfilter_ver(2);
435*82b0a103SAdrian Hunter }
436*82b0a103SAdrian Hunter 
437d68f0365SIan Rogers DEFINE_SUITE("dlfilter C API", dlfilter);
438