Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp269154imu; Wed, 21 Nov 2018 19:37:53 -0800 (PST) X-Google-Smtp-Source: AJdET5cYbd1lE/fBnxPToUe7qkq22MtNgYtFy3Y0UKS2MpAA9sw78qsoylORD0z8ttybNK0Itf4Q X-Received: by 2002:a62:6d83:: with SMTP id i125-v6mr9839837pfc.184.1542857873850; Wed, 21 Nov 2018 19:37:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542857873; cv=none; d=google.com; s=arc-20160816; b=bxhDuvOjO34OWnFS+3dKwntN6wp1SgqU5tYRMW+rkZHuHkZtNyS3rpXd1M1sBLmSKl V1g0XCVVBKyUaCMUyYaiAlpy5ZZeJVnF74WDofcstdonbfWqOiUbj8Sdio9DS9AoymCf 2eua6W2KlrUNgFrnOknxV1j0ZWg7MlRlASK/+rg3CQyc2OdZMsqSkW97dKTat+cysVwL +sMVNkEK9fspvIjcn79ky+kmIKaKHocpac2whAyKV6IlmuH22gkR/a3HFuje3BM1JtcR a4incQI3u5kpF+VW4VdqxgYCtMqg8hFTxp3dt5iIs+ZNtMGf/fs+sq5Er8pQ7/iad+JY L2oQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:smtp-origin-cluster:cc:to :smtp-origin-hostname:from:smtp-origin-hostprefix:dkim-signature; bh=nJKakrthfIJgfwRKNqTmJScjSewPYLj7kTi3oQyeBBI=; b=r8Qo6FYdCJ5kI2Jnc+jGstEe9k3sQalf1/imzkwYZ5ZXotUUYc5F2Xs6N1cwGqOz4f PqxNQrBosbam+1f2IOE8dUP+5PugnIM4dAGgTF+cHkW+q+8IRwCDhVMjdK1aYq6cq0Yy EoyBVerMtc3vnjH0EZ+NPX8tC0xlSjRxGrsjzPMfIOty+UmozOECxpUNPNtf9wBWsFoc qfiaswrU59BblBro8H6LPzUVsCci7T6ouzoLu4HyMWOpEDe8tObmgdyYHq//X5df8jhj oYD4GBaKmJYsj4fvDLS0ORdv/S3W1t+O4aWPxt6sOtdoRPYmV205QQzDqKJorm0RYkSt I/Mw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@fb.com header.s=facebook header.b=fLavb1S0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=fb.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y12si21039281pgh.289.2018.11.21.19.37.39; Wed, 21 Nov 2018 19:37:53 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@fb.com header.s=facebook header.b=fLavb1S0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=fb.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388030AbeKVGba (ORCPT + 99 others); Thu, 22 Nov 2018 01:31:30 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:59432 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387938AbeKVGba (ORCPT ); Thu, 22 Nov 2018 01:31:30 -0500 Received: from pps.filterd (m0044010.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id wALJtEaa013310 for ; Wed, 21 Nov 2018 11:55:47 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=nJKakrthfIJgfwRKNqTmJScjSewPYLj7kTi3oQyeBBI=; b=fLavb1S0eTTXOWDojAE2vh12jqQPBFB3zsE2rVj9vAxcKwtAuT+C/4BCfhyUzNOitVF0 sIrOt5Ua0WwEG3ODn0P4BEunj9n1uJwB/OT7Y5H2IgeIlQuOhhcflKhKHpix89bvaXFa AAqdaWwtRyUzpDBQbj3GGyDPag4j9C6QnJs= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 2nwc1cre9r-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Wed, 21 Nov 2018 11:55:46 -0800 Received: from mx-out.facebook.com (2620:10d:c0a1:3::13) by mail.thefacebook.com (2620:10d:c021:18::176) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1531.3; Wed, 21 Nov 2018 11:55:34 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 35FAF62E1AB8; Wed, 21 Nov 2018 11:55:34 -0800 (PST) Smtp-Origin-Hostprefix: devbig From: Song Liu Smtp-Origin-Hostname: devbig006.ftw2.facebook.com To: , CC: Song Liu , , , , , Smtp-Origin-Cluster: ftw2c04 Subject: [PATCH perf,bpf 4/5] perf util: introduce bpf_prog_info_event Date: Wed, 21 Nov 2018 11:55:01 -0800 Message-ID: <20181121195502.3259930-5-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181121195502.3259930-1-songliubraving@fb.com> References: <20181121195502.3259930-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-11-21_09:,, signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch introduces struct bpf_prog_info_event to union perf_event. struct bpf_prog_info_event { struct perf_event_header header; u32 prog_info_len; u32 ksym_table_len; u64 ksym_table; struct bpf_prog_info prog_info; char data[]; }; struct bpf_prog_info_event contains information about a bpf program. These events are written to perf.data by perf-record, and processed by perf-report. struct bpf_prog_info_event uses arrays for some data (ksym_table, and arrays in struct bpf_prog_info). To make these arrays easy to serialize, we allocate continuous memory (data). These array pointers are translated to offset in bpf_prog_info_event before written to file. And vice-versa when the event is read from file. This patch enables synthesizing these events at the beginning of perf-record run. Next patch will process short living bpf programs that are created during perf-record. Signed-off-by: Song Liu --- tools/perf/builtin-record.c | 8 + tools/perf/builtin-report.c | 2 + tools/perf/util/Build | 2 + tools/perf/util/bpf-info.c | 305 ++++++++++++++++++++++++++++++++++++ tools/perf/util/bpf-info.h | 29 ++++ tools/perf/util/event.c | 1 + tools/perf/util/event.h | 14 ++ tools/perf/util/session.c | 4 + tools/perf/util/tool.h | 3 +- 9 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 tools/perf/util/bpf-info.c create mode 100644 tools/perf/util/bpf-info.h diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0980dfe3396b..86dfba937e4e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -41,6 +41,7 @@ #include "util/perf-hooks.h" #include "util/time-utils.h" #include "util/units.h" +#include "util/bpf-info.h" #include "asm/bug.h" #include @@ -966,6 +967,12 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) if (err < 0) goto out_child; + err = perf_event__synthesize_bpf_prog_info( + &rec->tool, process_synthesized_event, + &rec->session->machines.host); + if (err < 0) + goto out_child; + if (rec->realtime_prio) { struct sched_param param; @@ -1531,6 +1538,7 @@ static struct record record = { .namespaces = perf_event__process_namespaces, .mmap = perf_event__process_mmap, .mmap2 = perf_event__process_mmap2, + .bpf_prog_info = perf_event__process_bpf_prog_info, .ordered_events = true, }, }; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c0703979c51d..4a9a3e8da4e0 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -41,6 +41,7 @@ #include "util/auxtrace.h" #include "util/units.h" #include "util/branch.h" +#include "util/bpf-info.h" #include #include @@ -981,6 +982,7 @@ int cmd_report(int argc, const char **argv) .auxtrace_info = perf_event__process_auxtrace_info, .auxtrace = perf_event__process_auxtrace, .feature = process_feature_event, + .bpf_prog_info = perf_event__process_bpf_prog_info, .ordered_events = true, .ordering_requires_timestamps = true, }, diff --git a/tools/perf/util/Build b/tools/perf/util/Build index ecd9f9ceda77..624c7281217c 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -150,6 +150,8 @@ endif libperf-y += perf-hooks.o +libperf-$(CONFIG_LIBBPF) += bpf-info.o + libperf-$(CONFIG_CXX) += c++/ CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" diff --git a/tools/perf/util/bpf-info.c b/tools/perf/util/bpf-info.c new file mode 100644 index 000000000000..2e0005677c43 --- /dev/null +++ b/tools/perf/util/bpf-info.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Facebook + */ +#include +#include +#include +#include "bpf-info.h" +#include "debug.h" +#include "session.h" + +#define KSYM_NAME_LEN 128 +#define BPF_PROG_INFO_MIN_SIZE 128 /* minimal require jited_func_lens */ + +static inline __u64 ptr_to_u64(const void *ptr) +{ + return (__u64) (unsigned long) ptr; +} + +static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len) +{ + int ret = 0; + size_t i; + + for (i = 0; i < len; i++) + ret += snprintf(buf + ret, size - ret, "%02x", data[i]); + return ret; +} + +/* fetch information of the bpf program via bpf syscall. */ +struct bpf_prog_info_event *perf_bpf_info__get_bpf_prog_info_event(int fd) +{ + struct bpf_prog_info_event *prog_info_event = NULL; + struct bpf_prog_info info = {}; + u32 info_len = sizeof(info); + u32 event_len, i; + void *ptr; + int err; + + err = bpf_obj_get_info_by_fd(fd, &info, &info_len); + if (err) { + pr_debug("can't get prog info: %s", strerror(errno)); + return NULL; + } + if (info_len < BPF_PROG_INFO_MIN_SIZE) { + pr_debug("kernel is too old to support proper prog info\n"); + return NULL; + } + + /* calculate size of bpf_prog_info_event */ + event_len = sizeof(struct bpf_prog_info_event); + event_len += info_len; + event_len -= sizeof(info); + event_len += info.jited_prog_len; + event_len += info.xlated_prog_len; + event_len += info.nr_map_ids * sizeof(u32); + event_len += info.nr_jited_ksyms * sizeof(u64); + event_len += info.nr_jited_func_lens * sizeof(u32); + event_len += info.nr_jited_ksyms * KSYM_NAME_LEN; + + prog_info_event = (struct bpf_prog_info_event *) malloc(event_len); + if (!prog_info_event) + return NULL; + + /* assign pointers for map_ids, jited_prog_insns, etc. */ + ptr = prog_info_event->data; + info.map_ids = ptr_to_u64(ptr); + ptr += info.nr_map_ids * sizeof(u32); + info.jited_prog_insns = ptr_to_u64(ptr); + ptr += info.jited_prog_len; + info.xlated_prog_insns = ptr_to_u64(ptr); + ptr += info.xlated_prog_len; + info.jited_ksyms = ptr_to_u64(ptr); + ptr += info.nr_jited_ksyms * sizeof(u64); + info.jited_func_lens = ptr_to_u64(ptr); + ptr += info.nr_jited_func_lens * sizeof(u32); + + err = bpf_obj_get_info_by_fd(fd, &info, &info_len); + if (err) { + pr_err("can't get prog info: %s\n", strerror(errno)); + free(prog_info_event); + return NULL; + } + + /* fill data in prog_info_event */ + prog_info_event->header.type = PERF_RECORD_BPF_PROG_INFO; + prog_info_event->header.misc = 0; + prog_info_event->prog_info_len = info_len; + + memcpy(&prog_info_event->prog_info, &info, info_len); + + prog_info_event->ksym_table_len = 0; + prog_info_event->ksym_table = ptr_to_u64(ptr); + + /* fill in fake symbol name for now, add real name after BTF */ + if (info.nr_jited_func_lens == 1 && info.name) { /* only main prog */ + size_t l; + + assert(info.nr_jited_ksyms == 1); + l = snprintf(ptr, KSYM_NAME_LEN, "bpf_prog_"); + l += snprintf_hex(ptr + l, KSYM_NAME_LEN - l, + prog_info_event->prog_info.tag, + BPF_TAG_SIZE); + l += snprintf(ptr + l, KSYM_NAME_LEN - l, "_%s", info.name); + prog_info_event->ksym_table_len += l + 1; + ptr += l + 1; + + } else { + assert(info.nr_jited_ksyms == info.nr_jited_func_lens); + + for (i = 0; i < info.nr_jited_ksyms; i++) { + size_t l; + + l = snprintf(ptr, KSYM_NAME_LEN, "bpf_prog_"); + l += snprintf_hex(ptr + l, KSYM_NAME_LEN - l, + prog_info_event->prog_info.tag, + BPF_TAG_SIZE); + l += snprintf(ptr + l, KSYM_NAME_LEN - l, "_F"); + prog_info_event->ksym_table_len += l + 1; + ptr += l + 1; + } + } + + prog_info_event->header.size = ptr - (void *)prog_info_event; + + return prog_info_event; +} + +static size_t fprintf_bpf_prog_info( + struct bpf_prog_info_event *prog_info_event, FILE *fp) +{ + struct bpf_prog_info *info = &prog_info_event->prog_info; + unsigned long *jited_ksyms = (unsigned long *)(info->jited_ksyms); + char *name_ptr = (char *) prog_info_event->ksym_table; + unsigned int i; + size_t ret; + + ret = fprintf(fp, "bpf_prog: type: %u id: %u ", info->type, info->id); + ret += fprintf(fp, "nr_jited_ksyms: %u\n", info->nr_jited_ksyms); + + for (i = 0; i < info->nr_jited_ksyms; i++) { + ret += fprintf(fp, "jited_ksyms[%u]: %lx %s\n", + i, jited_ksyms[i], name_ptr); + name_ptr += strlen(name_ptr); + } + return ret; +} + +size_t perf_event__fprintf_bpf_prog_info(union perf_event *event, FILE *fp) +{ + return fprintf_bpf_prog_info(&event->bpf_prog_info, fp); +} + +/* + * translate all array ptr to offset from base address, called before + * writing the event to file + */ +void perf_bpf_info__ptr_to_offset( + struct bpf_prog_info_event *prog_info_event) +{ + u64 base = ptr_to_u64(prog_info_event); + + prog_info_event->ksym_table -= base; + prog_info_event->prog_info.jited_prog_insns -= base; + prog_info_event->prog_info.xlated_prog_insns -= base; + prog_info_event->prog_info.map_ids -= base; + prog_info_event->prog_info.jited_ksyms -= base; + prog_info_event->prog_info.jited_func_lens -= base; +} + +/* + * translate offset from base address to array pointer, called after + * reading the event from file + */ +void perf_bpf_info__offset_to_ptr( + struct bpf_prog_info_event *prog_info_event) +{ + u64 base = ptr_to_u64(prog_info_event); + + prog_info_event->ksym_table += base; + prog_info_event->prog_info.jited_prog_insns += base; + prog_info_event->prog_info.xlated_prog_insns += base; + prog_info_event->prog_info.map_ids += base; + prog_info_event->prog_info.jited_ksyms += base; + prog_info_event->prog_info.jited_func_lens += base; +} + +int perf_event__synthesize_one_bpf_prog_info(struct perf_tool *tool, + perf_event__handler_t process, + struct machine *machine, + int fd) +{ + struct bpf_prog_info_event *prog_info_event; + + prog_info_event = perf_bpf_info__get_bpf_prog_info_event(fd); + + if (!prog_info_event) { + pr_err("Failed to get prog_info_event\n"); + return -1; + } + perf_bpf_info__ptr_to_offset(prog_info_event); + + if (perf_tool__process_synth_event( + tool, (union perf_event *)prog_info_event, + machine, process) != 0) { + free(prog_info_event); + return -1; + } + + free(prog_info_event); + return 0; +} + +int perf_event__synthesize_bpf_prog_info(struct perf_tool *tool, + perf_event__handler_t process, + struct machine *machine) +{ + __u32 id = 0; + int err = 0; + int fd; + + while (true) { + err = bpf_prog_get_next_id(id, &id); + if (err) { + if (errno == ENOENT) { + err = 0; + break; + } + pr_err("can't get next program: %s%s", + strerror(errno), + errno == EINVAL ? " -- kernel too old?" : ""); + err = -1; + break; + } + fd = bpf_prog_get_fd_by_id(id); + if (fd < 0) { + pr_debug("Failed to get fd for prog_id %u\n", id); + continue; + } + + err = perf_event__synthesize_one_bpf_prog_info( + tool, process, machine, fd); + close(fd); + if (err) + break; + } + return err; +} + +int perf_event__process_bpf_prog_info(struct perf_session *session, + union perf_event *event) +{ + struct machine *machine = &session->machines.host; + struct bpf_prog_info_event *prog_info_event; + struct bpf_prog_info *info; + struct symbol *sym; + struct map *map; + char *name_ptr; + int ret = 0; + u64 *addrs; + u32 *lens; + u32 i; + + prog_info_event = (struct bpf_prog_info_event *) + malloc(event->header.size); + if (!prog_info_event) + return -ENOMEM; + + /* copy the data to rw memeory so we can modify it */ + memcpy(prog_info_event, &event->bpf_prog_info, event->header.size); + info = &prog_info_event->prog_info; + + perf_bpf_info__offset_to_ptr(prog_info_event); + name_ptr = (char *) prog_info_event->ksym_table; + addrs = (u64 *)info->jited_ksyms; + lens = (u32 *)info->jited_func_lens; + for (i = 0; i < info->nr_jited_ksyms; i++) { + u32 len = info->nr_jited_func_lens == 1 ? + len = info->jited_prog_len : lens[i]; + + map = map_groups__find(&machine->kmaps, addrs[i]); + if (!map) { + map = dso__new_map("bpf_prog"); + if (!map) { + ret = -ENOMEM; + break; + } + map->start = addrs[i]; + map->pgoff = map->start; + map->end = map->start + len; + map_groups__insert(&machine->kmaps, map); + } + + sym = symbol__new(addrs[i], len, 0, 0, name_ptr); + if (!sym) { + ret = -ENOMEM; + break; + } + dso__insert_symbol(map->dso, sym); + name_ptr += strlen(name_ptr) + 1; + } + + free(prog_info_event); + return ret; +} diff --git a/tools/perf/util/bpf-info.h b/tools/perf/util/bpf-info.h new file mode 100644 index 000000000000..39d5da102017 --- /dev/null +++ b/tools/perf/util/bpf-info.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PERF_BPF_INFO_H +#define __PERF_BPF_INFO_H + +#include "event.h" +#include "machine.h" +#include "tool.h" +#include "symbol.h" + +struct bpf_prog_info_event *perf_bpf_info__get_bpf_prog_info_event(int fd); + +size_t perf_event__fprintf_bpf_prog_info(union perf_event *event, FILE *fp); + +int perf_event__synthesize_one_bpf_prog_info(struct perf_tool *tool, + perf_event__handler_t process, + struct machine *machine, + int fd); + +int perf_event__synthesize_bpf_prog_info(struct perf_tool *tool, + perf_event__handler_t process, + struct machine *machine); + +void perf_bpf_info__ptr_to_offset(struct bpf_prog_info_event *prog_info_event); +void perf_bpf_info__offset_to_ptr(struct bpf_prog_info_event *prog_info_event); + +int perf_event__process_bpf_prog_info(struct perf_session *session, + union perf_event *event); + +#endif /* __PERF_BPF_INFO_H */ diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 04104a4ffe93..de2a89faf445 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -62,6 +62,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", [PERF_RECORD_TIME_CONV] = "TIME_CONV", [PERF_RECORD_HEADER_FEATURE] = "FEATURE", + [PERF_RECORD_BPF_PROG_INFO] = "BPF_PROG_INFO", }; static const char *perf_ns__names[] = { diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 13a0c64dd0ed..dc64d800eaa6 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "../perf.h" #include "build-id.h" @@ -258,6 +259,7 @@ enum perf_user_event_type { /* above any possible kernel type */ PERF_RECORD_EVENT_UPDATE = 78, PERF_RECORD_TIME_CONV = 79, PERF_RECORD_HEADER_FEATURE = 80, + PERF_RECORD_BPF_PROG_INFO = 81, PERF_RECORD_HEADER_MAX }; @@ -629,6 +631,17 @@ struct feature_event { char data[]; }; +#define KSYM_NAME_LEN 128 + +struct bpf_prog_info_event { + struct perf_event_header header; + u32 prog_info_len; + u32 ksym_table_len; + u64 ksym_table; + struct bpf_prog_info prog_info; + char data[]; +}; + union perf_event { struct perf_event_header header; struct mmap_event mmap; @@ -661,6 +674,7 @@ union perf_event { struct time_conv_event time_conv; struct feature_event feat; struct bpf_event bpf_event; + struct bpf_prog_info_event bpf_prog_info; }; void perf_event__print_totals(void); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index dffe5120d2d3..5365ee1dfbec 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -415,6 +415,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->time_conv = process_event_op2_stub; if (tool->feature == NULL) tool->feature = process_event_op2_stub; + if (tool->bpf_prog_info == NULL) + tool->bpf_prog_info = process_event_op2_stub; } static void swap_sample_id_all(union perf_event *event, void *data) @@ -1397,6 +1399,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, return tool->time_conv(session, event); case PERF_RECORD_HEADER_FEATURE: return tool->feature(session, event); + case PERF_RECORD_BPF_PROG_INFO: + return tool->bpf_prog_info(session, event); default: return -EINVAL; } diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 69ae898ca024..739a4b1188f7 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -70,7 +70,8 @@ struct perf_tool { stat_config, stat, stat_round, - feature; + feature, + bpf_prog_info; event_op3 auxtrace; bool ordered_events; bool ordering_requires_timestamps; -- 2.17.1