From patchwork Wed Mar 6 07:13:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052140 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="L1Hchxzq"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlPY2m2nz9s9T for ; Wed, 6 Mar 2019 18:14:25 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729198AbfCFHOV (ORCPT ); Wed, 6 Mar 2019 02:14:21 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:39338 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729181AbfCFHOT (ORCPT ); Wed, 6 Mar 2019 02:14:19 -0500 Received: from pps.filterd (m0148460.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267DwK5003879 for ; Tue, 5 Mar 2019 23:14:17 -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=ZrZDcczo4vpZnSIhb1+K0nkCR0Uk73l7sK2TRzsEYmg=; b=L1HchxzqRDm/DZGpqdkgMXYG+jq1iBj/cbyOlT2XYg4gkt8AaLtxV4ylF018QY8zGc1u FMIAhi6KJs8DbHFsvuevebjKfRhJNx60m/JU2O2ss42zcCi+kOhGObAeZCFCKc9UMoo3 oaqt/Lx5As7ueZCtnk39MfP/B2D/HKGiSVA= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r28v8r3br-7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:17 -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.1713.5; Tue, 5 Mar 2019 23:14:10 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 9240B62E2965; Tue, 5 Mar 2019 23:14:09 -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 v6 perf, bpf 01/15] perf, bpf: consider events with attr.bpf_event as side-band events Date: Tue, 5 Mar 2019 23:13:45 -0800 Message-ID: <20190306071359.2359896-2-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Events with bpf_event should be considered as side-band event, as they carry information about BPF programs. Fixes: 6ee52e2a3fe4 ("perf, bpf: Introduce PERF_RECORD_BPF_EVENT") Signed-off-by: Song Liu --- kernel/events/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index f1a26c8f15b3..4a59cb9b29ee 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4238,7 +4238,8 @@ static bool is_sb_event(struct perf_event *event) if (attr->mmap || attr->mmap_data || attr->mmap2 || attr->comm || attr->comm_exec || attr->task || attr->ksymbol || - attr->context_switch) + attr->context_switch || + attr->bpf_event) return true; return false; } From patchwork Wed Mar 6 07:13:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052153 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="RQGlGJZA"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlRn3fqKz9s1B for ; Wed, 6 Mar 2019 18:16:21 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729166AbfCFHQT (ORCPT ); Wed, 6 Mar 2019 02:16:19 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:54918 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729157AbfCFHOP (ORCPT ); Wed, 6 Mar 2019 02:14:15 -0500 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267CjEY004881 for ; Tue, 5 Mar 2019 23:14:13 -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=6wJmJyke8j6ixD+nsOMkDgyb5heFyjac4iqefKfuvIU=; b=RQGlGJZAZFbn1pYSuYb/oiuG6xe/LmMDJ/KWeourenHLIuoWVlo+5Fi6EUQSwBx7eGTk ncEYahotLcsDUcJ/va3khG9My+S+sSRcQwxEV78MbsLTtplMrdPC1Xue72C6osgB9qrb BIjLb6Aw5k6/F30hOox9p2FBFvj2+7KXY8k= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r281ng6yy-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:13 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::126) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:12 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id C64D162E2965; Tue, 5 Mar 2019 23:14:11 -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 v6 perf, bpf 02/15] bpf: libbpf: introduce bpf_program__get_prog_info_linear() Date: Tue, 5 Mar 2019 23:13:46 -0800 Message-ID: <20190306071359.2359896-3-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Currently, bpf_prog_info includes 9 arrays. The user has the option to fetch any combination of these arrays. However, this requires a lot of handling of these arrays. This work becomes more tricky when we need to store bpf_prog_info to a file, because these arrays are allocated independently. This patch introduces struct bpf_prog_info_linear, which stores arrays of bpf_prog_info in continues memory. Helper functions are introduced to unify the work to get different information of bpf_prog_info. Specifically, bpf_program__get_prog_info_linear() allows the user to select which arrays to fetch, and handles details for the user. Plesae see the comments before enum bpf_prog_info_array for more details and examples. Cc: Daniel Borkmann Cc: Alexei Starovoitov Signed-off-by: Song Liu --- tools/lib/bpf/libbpf.c | 251 +++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 63 ++++++++++ tools/lib/bpf/libbpf.map | 3 + 3 files changed, 317 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index f5eb60379c8d..ca00ce5cbae0 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -112,6 +112,11 @@ void libbpf_print(enum libbpf_print_level level, const char *format, ...) # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ #endif +static inline __u64 ptr_to_u64(const void *ptr) +{ + return (__u64) (unsigned long) ptr; +} + struct bpf_capabilities { /* v4.14: kernel support for program & map names. */ __u32 name:1; @@ -2997,3 +3002,249 @@ bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size, ring_buffer_write_tail(header, data_tail); return ret; } + +struct bpf_prog_info_array_desc { + int array_offset; /* e.g. offset of jited_prog_insns */ + int count_offset; /* e.g. offset of jited_prog_len */ + int size_offset; /* > 0: offset of rec size, + * < 0: fix size of -size_offset + */ +}; + +static struct bpf_prog_info_array_desc bpf_prog_info_array_desc[] = { + [BPF_PROG_INFO_JITED_INSNS] = { + offsetof(struct bpf_prog_info, jited_prog_insns), + offsetof(struct bpf_prog_info, jited_prog_len), + -1, + }, + [BPF_PROG_INFO_XLATED_INSNS] = { + offsetof(struct bpf_prog_info, xlated_prog_insns), + offsetof(struct bpf_prog_info, xlated_prog_len), + -1, + }, + [BPF_PROG_INFO_MAP_IDS] = { + offsetof(struct bpf_prog_info, map_ids), + offsetof(struct bpf_prog_info, nr_map_ids), + -(int)sizeof(__u32), + }, + [BPF_PROG_INFO_JITED_KSYMS] = { + offsetof(struct bpf_prog_info, jited_ksyms), + offsetof(struct bpf_prog_info, nr_jited_ksyms), + -(int)sizeof(__u64), + }, + [BPF_PROG_INFO_JITED_FUNC_LENS] = { + offsetof(struct bpf_prog_info, jited_func_lens), + offsetof(struct bpf_prog_info, nr_jited_func_lens), + -(int)sizeof(__u32), + }, + [BPF_PROG_INFO_FUNC_INFO] = { + offsetof(struct bpf_prog_info, func_info), + offsetof(struct bpf_prog_info, nr_func_info), + offsetof(struct bpf_prog_info, func_info_rec_size), + }, + [BPF_PROG_INFO_LINE_INFO] = { + offsetof(struct bpf_prog_info, line_info), + offsetof(struct bpf_prog_info, nr_line_info), + offsetof(struct bpf_prog_info, line_info_rec_size), + }, + [BPF_PROG_INFO_JITED_LINE_INFO] = { + offsetof(struct bpf_prog_info, jited_line_info), + offsetof(struct bpf_prog_info, nr_jited_line_info), + offsetof(struct bpf_prog_info, jited_line_info_rec_size), + }, + [BPF_PROG_INFO_PROG_TAGS] = { + offsetof(struct bpf_prog_info, prog_tags), + offsetof(struct bpf_prog_info, nr_prog_tags), + -(int)sizeof(__u8) * BPF_TAG_SIZE, + }, + +}; + +static __u32 bpf_prog_info_read_offset_u32(struct bpf_prog_info *info, int offset) +{ + __u32 *array = (__u32 *)info; + + if (offset >= 0) + return array[offset / sizeof(__u32)]; + return -(int)offset; +} + +static __u64 bpf_prog_info_read_offset_u64(struct bpf_prog_info *info, int offset) +{ + __u64 *array = (__u64 *)info; + + if (offset >= 0) + return array[offset / sizeof(__u64)]; + return -(int)offset; +} + +static void bpf_prog_info_set_offset_u32(struct bpf_prog_info *info, int offset, + __u32 val) +{ + __u32 *array = (__u32 *)info; + + if (offset >= 0) + array[offset / sizeof(__u32)] = val; +} + +static void bpf_prog_info_set_offset_u64(struct bpf_prog_info *info, int offset, + __u64 val) +{ + __u64 *array = (__u64 *)info; + + if (offset >= 0) + array[offset / sizeof(__u64)] = val; +} + +struct bpf_prog_info_linear * +bpf_program__get_prog_info_linear(int fd, __u64 arrays) +{ + struct bpf_prog_info_linear *info_linear; + struct bpf_prog_info info = {}; + __u32 info_len = sizeof(info); + __u32 data_len = 0; + int i, err; + void *ptr; + + if (arrays >> BPF_PROG_INFO_LAST_ARRAY) + return ERR_PTR(-EINVAL); + + /* step 1: get array dimensions */ + err = bpf_obj_get_info_by_fd(fd, &info, &info_len); + if (err) { + pr_debug("can't get prog info: %s", strerror(errno)); + return ERR_PTR(-EFAULT); + } + + /* step 2: calculate total size of all arrays */ + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { + bool include_array = (arrays & (1UL << i)) > 0; + struct bpf_prog_info_array_desc *desc; + __u32 count, size; + + desc = bpf_prog_info_array_desc + i; + + /* kernel is too old to support this field */ + if (info_len < desc->array_offset + sizeof(__u32) || + info_len < desc->count_offset + sizeof(__u32) || + (desc->size_offset > 0 && info_len < desc->size_offset)) + include_array = false; + + if (!include_array) { + arrays &= ~(1UL << i); /* clear the bit */ + continue; + } + + count = bpf_prog_info_read_offset_u32(&info, desc->count_offset); + size = bpf_prog_info_read_offset_u32(&info, desc->size_offset); + + data_len += count * size; + } + + /* step 3: allocate continuous memory */ + data_len = roundup(data_len, sizeof(__u64)); + info_linear = malloc(sizeof(struct bpf_prog_info_linear) + data_len); + if (!info_linear) + return ERR_PTR(-ENOMEM); + + /* step 4: fill data to info_linear->info */ + info_linear->arrays = arrays; + memset(&info_linear->info, 0, sizeof(info)); + ptr = info_linear->data; + + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { + struct bpf_prog_info_array_desc *desc; + __u32 count, size; + + if ((arrays & (1UL << i)) == 0) + continue; + + desc = bpf_prog_info_array_desc + i; + count = bpf_prog_info_read_offset_u32(&info, desc->count_offset); + size = bpf_prog_info_read_offset_u32(&info, desc->size_offset); + bpf_prog_info_set_offset_u32(&info_linear->info, + desc->count_offset, count); + bpf_prog_info_set_offset_u32(&info_linear->info, + desc->size_offset, size); + bpf_prog_info_set_offset_u64(&info_linear->info, + desc->array_offset, + ptr_to_u64(ptr)); + ptr += count * size; + } + + /* step 5: call syscall again to get required arrays */ + err = bpf_obj_get_info_by_fd(fd, &info_linear->info, &info_len); + if (err) { + pr_debug("can't get prog info: %s", strerror(errno)); + free(info_linear); + return ERR_PTR(-EFAULT); + } + + /* step 6: verify the data */ + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { + struct bpf_prog_info_array_desc *desc; + __u32 v1, v2; + + if ((arrays & (1UL << i)) == 0) + continue; + + desc = bpf_prog_info_array_desc + i; + v1 = bpf_prog_info_read_offset_u32(&info, desc->count_offset); + v2 = bpf_prog_info_read_offset_u32(&info_linear->info, + desc->count_offset); + if (v1 != v2) + pr_warning("%s: mismatch in element count\n", __func__); + + v1 = bpf_prog_info_read_offset_u32(&info, desc->size_offset); + v2 = bpf_prog_info_read_offset_u32(&info_linear->info, + desc->size_offset); + if (v1 != v2) + pr_warning("%s: mismatch in rec size\n", __func__); + } + + /* step 7: update info_len and data_len */ + info_linear->info_len = sizeof(struct bpf_prog_info); + info_linear->data_len = data_len; + + return info_linear; +} + +void bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear) +{ + int i; + + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { + struct bpf_prog_info_array_desc *desc; + __u64 addr, offs; + + if ((info_linear->arrays & (1UL << i)) == 0) + continue; + + desc = bpf_prog_info_array_desc + i; + addr = bpf_prog_info_read_offset_u64(&info_linear->info, + desc->array_offset); + offs = addr - ptr_to_u64(info_linear->data); + bpf_prog_info_set_offset_u64(&info_linear->info, + desc->array_offset, offs); + } +} + +void bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear) +{ + int i; + + for (i = BPF_PROG_INFO_FIRST_ARRAY; i < BPF_PROG_INFO_LAST_ARRAY; ++i) { + struct bpf_prog_info_array_desc *desc; + __u64 addr, offs; + + if ((info_linear->arrays & (1UL << i)) == 0) + continue; + + desc = bpf_prog_info_array_desc + i; + offs = bpf_prog_info_read_offset_u64(&info_linear->info, + desc->array_offset); + addr = offs + ptr_to_u64(info_linear->data); + bpf_prog_info_set_offset_u64(&info_linear->info, + desc->array_offset, addr); + } +} diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index b4652aa1a58a..c7645a5e1ac0 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -377,6 +377,69 @@ LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex); LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type, __u32 ifindex); +/* + * Get bpf_prog_info in continuous memory + * + * struct bpf_prog_info has multiple arrays. The user has option to choose + * arrays to fetch from kernel. The following APIs provide uniform way to + * fetch these data. All arrays in bpf_prog_info are stored in singile + * continuous memory region. This makes it easy to store the info in a + * file. + * + * Before writing bpf_prog_info_linear to files, it is necessary to + * translate pointers bpf_prog_info to offsets. Helper functions + * bpf_program__bpil_addr_to_offs() and bpf_program__bpil_offs_to_addr() + * are introduced to switch between pointers and offsets. + * + * Examples: + * # To fetch map_ids and prog_tags: + * __u64 arrays = (1UL << BPF_PROG_INFO_MAP_IDS) | + * (1UL << BPF_PROG_INFO_PROG_TAGS); + * struct bpf_prog_info_linear *info_linear = + * bpf_program__get_prog_info_linear(fd, arrays); + * + * # To save data in file + * bpf_program__bpil_addr_to_offs(info_linear); + * write(f, info_linear, sizeof(*info_linear) + info_linear->data_len); + * + * # To read data from file + * read(f, info_linear, ); + * bpf_program__bpil_offs_to_addr(info_linear); + */ +enum bpf_prog_info_array { + BPF_PROG_INFO_FIRST_ARRAY = 0, + BPF_PROG_INFO_JITED_INSNS = 0, + BPF_PROG_INFO_XLATED_INSNS, + BPF_PROG_INFO_MAP_IDS, + BPF_PROG_INFO_JITED_KSYMS, + BPF_PROG_INFO_JITED_FUNC_LENS, + BPF_PROG_INFO_FUNC_INFO, + BPF_PROG_INFO_LINE_INFO, + BPF_PROG_INFO_JITED_LINE_INFO, + BPF_PROG_INFO_PROG_TAGS, + BPF_PROG_INFO_LAST_ARRAY, +}; + +struct bpf_prog_info_linear { + /* size of struct bpf_prog_info, when the tool is compiled */ + __u32 info_len; + /* total bytes allocated for data, round up to 8 bytes */ + __u32 data_len; + /* which arrays are included in data */ + __u64 arrays; + struct bpf_prog_info info; + __u8 data[]; +}; + +LIBBPF_API struct bpf_prog_info_linear * +bpf_program__get_prog_info_linear(int fd, __u64 arrays); + +LIBBPF_API void +bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear); + +LIBBPF_API void +bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 778a26702a70..f3ce50500cf2 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -153,4 +153,7 @@ LIBBPF_0.0.2 { xsk_socket__delete; xsk_umem__fd; xsk_socket__fd; + bpf_program__get_prog_info_linear; + bpf_program__bpil_addr_to_offs; + bpf_program__bpil_offs_to_addr; } LIBBPF_0.0.1; From patchwork Wed Mar 6 07:13:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052139 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="M+9B2AAM"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlPX1j96z9sNG for ; Wed, 6 Mar 2019 18:14:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729180AbfCFHOS (ORCPT ); Wed, 6 Mar 2019 02:14:18 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:33360 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729151AbfCFHOR (ORCPT ); Wed, 6 Mar 2019 02:14:17 -0500 Received: from pps.filterd (m0109334.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267CjvI026565 for ; Tue, 5 Mar 2019 23:14:16 -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=QwFf4DqjexQFHa0mdPsjnwyPkFQhHbNv0RT0RDdCT9U=; b=M+9B2AAM+Jm9XMjxUqbMGgMZER7BuuPkUzyc3nZudv8r/4BoB6MzRqhN/CUF9HGPs8JC OV3HAKniHKjdfV85dGi1UAzIrQ1qNn/Ye2D3g4NRRptrZEaZce6fqBnwOVMlCQ1wdYQ/ H1JHSIfsQIC5IRWAwoztBL4o51/r1ZvOXhc= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r28b3g61q-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:16 -0800 Received: from mx-out.facebook.com (2620:10d:c0a1:3::13) by mail.thefacebook.com (2620:10d:c021:18::174) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:14 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id EB02762E2965; Tue, 5 Mar 2019 23:14:13 -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 v6 perf, bpf 03/15] bpf: bpftool: use bpf_program__get_prog_info_linear() in prog.c:do_dump() Date: Tue, 5 Mar 2019 23:13:47 -0800 Message-ID: <20190306071359.2359896-4-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patches uses bpf_program__get_prog_info_linear() to simplify the logic in prog.c do_dump(). Cc: Daniel Borkmann Cc: Alexei Starovoitov Signed-off-by: Song Liu --- tools/bpf/bpftool/prog.c | 266 +++++++++------------------------------ 1 file changed, 59 insertions(+), 207 deletions(-) diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 8ef80d65a474..d2be5a06c339 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -401,41 +401,31 @@ static int do_show(int argc, char **argv) static int do_dump(int argc, char **argv) { - unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size; - void *func_info = NULL, *linfo = NULL, *jited_linfo = NULL; - unsigned int nr_finfo, nr_linfo = 0, nr_jited_linfo = 0; + struct bpf_prog_info_linear *info_linear; struct bpf_prog_linfo *prog_linfo = NULL; - unsigned long *func_ksyms = NULL; - struct bpf_prog_info info = {}; - unsigned int *func_lens = NULL; + enum {DUMP_JITED, DUMP_XLATED} mode; const char *disasm_opt = NULL; - unsigned int nr_func_ksyms; - unsigned int nr_func_lens; + struct bpf_prog_info *info; struct dump_data dd = {}; - __u32 len = sizeof(info); + void *func_info = NULL; struct btf *btf = NULL; - unsigned int buf_size; char *filepath = NULL; bool opcodes = false; bool visual = false; char func_sig[1024]; unsigned char *buf; bool linum = false; - __u32 *member_len; - __u64 *member_ptr; + __u32 member_len; + __u64 arrays; ssize_t n; - int err; int fd; if (is_prefix(*argv, "jited")) { if (disasm_init()) return -1; - - member_len = &info.jited_prog_len; - member_ptr = &info.jited_prog_insns; + mode = DUMP_JITED; } else if (is_prefix(*argv, "xlated")) { - member_len = &info.xlated_prog_len; - member_ptr = &info.xlated_prog_insns; + mode = DUMP_XLATED; } else { p_err("expected 'xlated' or 'jited', got: %s", *argv); return -1; @@ -474,175 +464,50 @@ static int do_dump(int argc, char **argv) return -1; } - err = bpf_obj_get_info_by_fd(fd, &info, &len); - if (err) { - p_err("can't get prog info: %s", strerror(errno)); - return -1; - } - - if (!*member_len) { - p_info("no instructions returned"); - close(fd); - return 0; - } + if (mode == DUMP_JITED) + arrays = 1UL << BPF_PROG_INFO_JITED_INSNS; + else + arrays = 1UL << BPF_PROG_INFO_XLATED_INSNS; - buf_size = *member_len; + arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS; + arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; + arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; - buf = malloc(buf_size); - if (!buf) { - p_err("mem alloc failed"); - close(fd); + info_linear = bpf_program__get_prog_info_linear(fd, arrays); + close(fd); + if (IS_ERR_OR_NULL(info_linear)) { + p_err("can't get prog info: %s", strerror(errno)); return -1; } - nr_func_ksyms = info.nr_jited_ksyms; - if (nr_func_ksyms) { - func_ksyms = malloc(nr_func_ksyms * sizeof(__u64)); - if (!func_ksyms) { - p_err("mem alloc failed"); - close(fd); - goto err_free; - } - } - - nr_func_lens = info.nr_jited_func_lens; - if (nr_func_lens) { - func_lens = malloc(nr_func_lens * sizeof(__u32)); - if (!func_lens) { - p_err("mem alloc failed"); - close(fd); + info = &info_linear->info; + if (mode == DUMP_JITED) { + if (info->jited_prog_len == 0) { + p_info("no instructions returned"); goto err_free; } - } - - nr_finfo = info.nr_func_info; - finfo_rec_size = info.func_info_rec_size; - if (nr_finfo && finfo_rec_size) { - func_info = malloc(nr_finfo * finfo_rec_size); - if (!func_info) { - p_err("mem alloc failed"); - close(fd); + buf = (unsigned char *)(info->jited_prog_insns); + member_len = info->jited_prog_len; + } else { /* DUMP_XLATED */ + if (info->xlated_prog_len == 0) { + p_err("error retrieving insn dump: kernel.kptr_restrict set?"); goto err_free; } + buf = (unsigned char *)info->xlated_prog_insns; + member_len = info->xlated_prog_len; } - linfo_rec_size = info.line_info_rec_size; - if (info.nr_line_info && linfo_rec_size && info.btf_id) { - nr_linfo = info.nr_line_info; - linfo = malloc(nr_linfo * linfo_rec_size); - if (!linfo) { - p_err("mem alloc failed"); - close(fd); - goto err_free; - } - } - - jited_linfo_rec_size = info.jited_line_info_rec_size; - if (info.nr_jited_line_info && - jited_linfo_rec_size && - info.nr_jited_ksyms && - info.nr_jited_func_lens && - info.btf_id) { - nr_jited_linfo = info.nr_jited_line_info; - jited_linfo = malloc(nr_jited_linfo * jited_linfo_rec_size); - if (!jited_linfo) { - p_err("mem alloc failed"); - close(fd); - goto err_free; - } - } - - memset(&info, 0, sizeof(info)); - - *member_ptr = ptr_to_u64(buf); - *member_len = buf_size; - info.jited_ksyms = ptr_to_u64(func_ksyms); - info.nr_jited_ksyms = nr_func_ksyms; - info.jited_func_lens = ptr_to_u64(func_lens); - info.nr_jited_func_lens = nr_func_lens; - info.nr_func_info = nr_finfo; - info.func_info_rec_size = finfo_rec_size; - info.func_info = ptr_to_u64(func_info); - info.nr_line_info = nr_linfo; - info.line_info_rec_size = linfo_rec_size; - info.line_info = ptr_to_u64(linfo); - info.nr_jited_line_info = nr_jited_linfo; - info.jited_line_info_rec_size = jited_linfo_rec_size; - info.jited_line_info = ptr_to_u64(jited_linfo); - - err = bpf_obj_get_info_by_fd(fd, &info, &len); - close(fd); - if (err) { - p_err("can't get prog info: %s", strerror(errno)); - goto err_free; - } - - if (*member_len > buf_size) { - p_err("too many instructions returned"); - goto err_free; - } - - if (info.nr_jited_ksyms > nr_func_ksyms) { - p_err("too many addresses returned"); - goto err_free; - } - - if (info.nr_jited_func_lens > nr_func_lens) { - p_err("too many values returned"); - goto err_free; - } - - if (info.nr_func_info != nr_finfo) { - p_err("incorrect nr_func_info %d vs. expected %d", - info.nr_func_info, nr_finfo); - goto err_free; - } - - if (info.func_info_rec_size != finfo_rec_size) { - p_err("incorrect func_info_rec_size %d vs. expected %d", - info.func_info_rec_size, finfo_rec_size); - goto err_free; - } - - if (linfo && info.nr_line_info != nr_linfo) { - p_err("incorrect nr_line_info %u vs. expected %u", - info.nr_line_info, nr_linfo); - goto err_free; - } - - if (info.line_info_rec_size != linfo_rec_size) { - p_err("incorrect line_info_rec_size %u vs. expected %u", - info.line_info_rec_size, linfo_rec_size); - goto err_free; - } - - if (jited_linfo && info.nr_jited_line_info != nr_jited_linfo) { - p_err("incorrect nr_jited_line_info %u vs. expected %u", - info.nr_jited_line_info, nr_jited_linfo); - goto err_free; - } - - if (info.jited_line_info_rec_size != jited_linfo_rec_size) { - p_err("incorrect jited_line_info_rec_size %u vs. expected %u", - info.jited_line_info_rec_size, jited_linfo_rec_size); - goto err_free; - } - - if ((member_len == &info.jited_prog_len && - info.jited_prog_insns == 0) || - (member_len == &info.xlated_prog_len && - info.xlated_prog_insns == 0)) { - p_err("error retrieving insn dump: kernel.kptr_restrict set?"); - goto err_free; - } - - if (info.btf_id && btf__get_from_id(info.btf_id, &btf)) { + if (info->btf_id && btf__get_from_id(info->btf_id, &btf)) { p_err("failed to get btf"); goto err_free; } - if (nr_linfo) { - prog_linfo = bpf_prog_linfo__new(&info); + func_info = (void *)info->func_info; + + if (info->nr_line_info) { + prog_linfo = bpf_prog_linfo__new(info); if (!prog_linfo) p_info("error in processing bpf_line_info. continue without it."); } @@ -655,9 +520,9 @@ static int do_dump(int argc, char **argv) goto err_free; } - n = write(fd, buf, *member_len); + n = write(fd, buf, member_len); close(fd); - if (n != *member_len) { + if (n != member_len) { p_err("error writing output file: %s", n < 0 ? strerror(errno) : "short write"); goto err_free; @@ -665,19 +530,19 @@ static int do_dump(int argc, char **argv) if (json_output) jsonw_null(json_wtr); - } else if (member_len == &info.jited_prog_len) { + } else if (mode == DUMP_JITED) { const char *name = NULL; - if (info.ifindex) { - name = ifindex_to_bfd_params(info.ifindex, - info.netns_dev, - info.netns_ino, + if (info->ifindex) { + name = ifindex_to_bfd_params(info->ifindex, + info->netns_dev, + info->netns_ino, &disasm_opt); if (!name) goto err_free; } - if (info.nr_jited_func_lens && info.jited_func_lens) { + if (info->nr_jited_func_lens && info->jited_func_lens) { struct kernel_sym *sym = NULL; struct bpf_func_info *record; char sym_name[SYM_MAX_NAME]; @@ -685,17 +550,16 @@ static int do_dump(int argc, char **argv) __u64 *ksyms = NULL; __u32 *lens; __u32 i; - - if (info.nr_jited_ksyms) { + if (info->nr_jited_ksyms) { kernel_syms_load(&dd); - ksyms = (__u64 *) info.jited_ksyms; + ksyms = (__u64 *) info->jited_ksyms; } if (json_output) jsonw_start_array(json_wtr); - lens = (__u32 *) info.jited_func_lens; - for (i = 0; i < info.nr_jited_func_lens; i++) { + lens = (__u32 *) info->jited_func_lens; + for (i = 0; i < info->nr_jited_func_lens; i++) { if (ksyms) { sym = kernel_syms_search(&dd, ksyms[i]); if (sym) @@ -707,7 +571,7 @@ static int do_dump(int argc, char **argv) } if (func_info) { - record = func_info + i * finfo_rec_size; + record = func_info + i * info->func_info_rec_size; btf_dumper_type_only(btf, record->type_id, func_sig, sizeof(func_sig)); @@ -744,49 +608,37 @@ static int do_dump(int argc, char **argv) if (json_output) jsonw_end_array(json_wtr); } else { - disasm_print_insn(buf, *member_len, opcodes, name, + disasm_print_insn(buf, member_len, opcodes, name, disasm_opt, btf, NULL, 0, 0, false); } } else if (visual) { if (json_output) jsonw_null(json_wtr); else - dump_xlated_cfg(buf, *member_len); + dump_xlated_cfg(buf, member_len); } else { kernel_syms_load(&dd); - dd.nr_jited_ksyms = info.nr_jited_ksyms; - dd.jited_ksyms = (__u64 *) info.jited_ksyms; + dd.nr_jited_ksyms = info->nr_jited_ksyms; + dd.jited_ksyms = (__u64 *) info->jited_ksyms; dd.btf = btf; dd.func_info = func_info; - dd.finfo_rec_size = finfo_rec_size; + dd.finfo_rec_size = info->func_info_rec_size; dd.prog_linfo = prog_linfo; if (json_output) - dump_xlated_json(&dd, buf, *member_len, opcodes, + dump_xlated_json(&dd, buf, member_len, opcodes, linum); else - dump_xlated_plain(&dd, buf, *member_len, opcodes, + dump_xlated_plain(&dd, buf, member_len, opcodes, linum); kernel_syms_destroy(&dd); } - free(buf); - free(func_ksyms); - free(func_lens); - free(func_info); - free(linfo); - free(jited_linfo); - bpf_prog_linfo__free(prog_linfo); + free(info_linear); return 0; err_free: - free(buf); - free(func_ksyms); - free(func_lens); - free(func_info); - free(linfo); - free(jited_linfo); - bpf_prog_linfo__free(prog_linfo); + free(info_linear); return -1; } From patchwork Wed Mar 6 07:13:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052141 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="QAKSV3xN"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlPZ1H7mz9sMx for ; Wed, 6 Mar 2019 18:14:26 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729207AbfCFHOW (ORCPT ); Wed, 6 Mar 2019 02:14:22 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:40472 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729190AbfCFHOV (ORCPT ); Wed, 6 Mar 2019 02:14:21 -0500 Received: from pps.filterd (m0001303.ppops.net [127.0.0.1]) by m0001303.ppops.net (8.16.0.27/8.16.0.27) with SMTP id x267DO2B015939 for ; Tue, 5 Mar 2019 23:14:19 -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=3f1/7dNVoU4JrPYZXuXMuxBJH9f0uYqRb7kWZjII/UI=; b=QAKSV3xNJBSui9RUxGyzT4DsWXpUF4uRJ0Lx2T/LkPxJQJjY47qzENVX0OE2yRGOxcVk RsjqoEqT4e0uq0Xv93004zvL86HICfqb9TaQReKDqBNBNj8e/fcje/qs6ShQ04LGQDef leWCZfG7AYDIIc2ah2dYrz6cDi07vExD6nY= Received: from maileast.thefacebook.com ([199.201.65.23]) by m0001303.ppops.net with ESMTP id 2r23ac0xu9-10 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:19 -0800 Received: from mx-out.facebook.com (2620:10d:c0a1:3::13) by mail.thefacebook.com (2620:10d:c021:18::173) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:17 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 1D74F62E2965; Tue, 5 Mar 2019 23:14:16 -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 v6 perf, bpf 04/15] perf, bpf: synthesize bpf events with bpf_program__get_prog_info_linear() Date: Tue, 5 Mar 2019 23:13:48 -0800 Message-ID: <20190306071359.2359896-5-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org With bpf_program__get_prog_info_linear, we can simplify the logic that synthesizes bpf events. This patch doesn't change the behavior of the code. Signed-off-by: Song Liu --- tools/perf/util/bpf-event.c | 118 ++++++++++++------------------------ 1 file changed, 40 insertions(+), 78 deletions(-) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 796ef793f4ce..e6dfb95029e5 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include "bpf-event.h" #include "debug.h" #include "symbol.h" @@ -49,99 +51,62 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, { struct ksymbol_event *ksymbol_event = &event->ksymbol_event; struct bpf_event *bpf_event = &event->bpf_event; - u32 sub_prog_cnt, i, func_info_rec_size = 0; - u8 (*prog_tags)[BPF_TAG_SIZE] = NULL; - struct bpf_prog_info info = { .type = 0, }; - u32 info_len = sizeof(info); - void *func_infos = NULL; - u64 *prog_addrs = NULL; + struct bpf_prog_info_linear *info_linear; + struct bpf_prog_info *info; struct btf *btf = NULL; - u32 *prog_lens = NULL; bool has_btf = false; - char errbuf[512]; + u32 sub_prog_cnt, i; int err = 0; + u64 arrays; - /* Call bpf_obj_get_info_by_fd() to get sizes of arrays */ - err = bpf_obj_get_info_by_fd(fd, &info, &info_len); + arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS; + arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; + arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS; - if (err) { - pr_debug("%s: failed to get BPF program info: %s, aborting\n", - __func__, str_error_r(errno, errbuf, sizeof(errbuf))); + info_linear = bpf_program__get_prog_info_linear(fd, arrays); + if (IS_ERR_OR_NULL(info_linear)) { + info_linear = NULL; + pr_debug("%s: failed to get BPF program info. aborting\n", __func__); return -1; } - if (info_len < offsetof(struct bpf_prog_info, prog_tags)) { + + if (info_linear->info_len < offsetof(struct bpf_prog_info, prog_tags)) { pr_debug("%s: the kernel is too old, aborting\n", __func__); return -2; } + info = &info_linear->info; + /* number of ksyms, func_lengths, and tags should match */ - sub_prog_cnt = info.nr_jited_ksyms; - if (sub_prog_cnt != info.nr_prog_tags || - sub_prog_cnt != info.nr_jited_func_lens) + sub_prog_cnt = info->nr_jited_ksyms; + if (sub_prog_cnt != info->nr_prog_tags || + sub_prog_cnt != info->nr_jited_func_lens) return -1; /* check BTF func info support */ - if (info.btf_id && info.nr_func_info && info.func_info_rec_size) { + if (info->btf_id && info->nr_func_info && info->func_info_rec_size) { /* btf func info number should be same as sub_prog_cnt */ - if (sub_prog_cnt != info.nr_func_info) { + if (sub_prog_cnt != info->nr_func_info) { pr_debug("%s: mismatch in BPF sub program count and BTF function info count, aborting\n", __func__); - return -1; - } - if (btf__get_from_id(info.btf_id, &btf)) { - pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info.btf_id); - return -1; + err = -1; + goto out; } - func_info_rec_size = info.func_info_rec_size; - func_infos = calloc(sub_prog_cnt, func_info_rec_size); - if (!func_infos) { - pr_debug("%s: failed to allocate memory for func_infos, aborting\n", __func__); - return -1; + if (btf__get_from_id(info->btf_id, &btf)) { + pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info->btf_id); + err = -1; + btf = NULL; + goto out; } has_btf = true; } - /* - * We need address, length, and tag for each sub program. - * Allocate memory and call bpf_obj_get_info_by_fd() again - */ - prog_addrs = calloc(sub_prog_cnt, sizeof(u64)); - if (!prog_addrs) { - pr_debug("%s: failed to allocate memory for prog_addrs, aborting\n", __func__); - goto out; - } - prog_lens = calloc(sub_prog_cnt, sizeof(u32)); - if (!prog_lens) { - pr_debug("%s: failed to allocate memory for prog_lens, aborting\n", __func__); - goto out; - } - prog_tags = calloc(sub_prog_cnt, BPF_TAG_SIZE); - if (!prog_tags) { - pr_debug("%s: failed to allocate memory for prog_tags, aborting\n", __func__); - goto out; - } - - memset(&info, 0, sizeof(info)); - info.nr_jited_ksyms = sub_prog_cnt; - info.nr_jited_func_lens = sub_prog_cnt; - info.nr_prog_tags = sub_prog_cnt; - info.jited_ksyms = ptr_to_u64(prog_addrs); - info.jited_func_lens = ptr_to_u64(prog_lens); - info.prog_tags = ptr_to_u64(prog_tags); - info_len = sizeof(info); - if (has_btf) { - info.nr_func_info = sub_prog_cnt; - info.func_info_rec_size = func_info_rec_size; - info.func_info = ptr_to_u64(func_infos); - } - - err = bpf_obj_get_info_by_fd(fd, &info, &info_len); - if (err) { - pr_debug("%s: failed to get BPF program info, aborting\n", __func__); - goto out; - } - /* Synthesize PERF_RECORD_KSYMBOL */ for (i = 0; i < sub_prog_cnt; i++) { + u8 (*prog_tags)[BPF_TAG_SIZE] = (void *)(info->prog_tags); + __u32 *prog_lens = (__u32 *)(info->jited_func_lens); + __u64 *prog_addrs = (__u64 *)(info->jited_ksyms); + void *func_infos = (void *)(info->func_info); const struct bpf_func_info *finfo; const char *short_name = NULL; const struct btf_type *t; @@ -163,13 +128,13 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, KSYM_NAME_LEN - name_len, prog_tags[i], BPF_TAG_SIZE); if (has_btf) { - finfo = func_infos + i * info.func_info_rec_size; + finfo = func_infos + i * info->func_info_rec_size; t = btf__type_by_id(btf, finfo->type_id); short_name = btf__name_by_offset(btf, t->name_off); } else if (i == 0 && sub_prog_cnt == 1) { /* no subprog */ - if (info.name[0]) - short_name = info.name; + if (info->name[0]) + short_name = info->name; } else short_name = "F"; if (short_name) @@ -195,9 +160,9 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, }, .type = PERF_BPF_EVENT_PROG_LOAD, .flags = 0, - .id = info.id, + .id = info->id, }; - memcpy(bpf_event->tag, prog_tags[i], BPF_TAG_SIZE); + memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE); memset((void *)event + event->header.size, 0, machine->id_hdr_size); event->header.size += machine->id_hdr_size; err = perf_tool__process_synth_event(tool, event, @@ -205,10 +170,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, } out: - free(prog_tags); - free(prog_lens); - free(prog_addrs); - free(func_infos); + free(info_linear); free(btf); return err ? -1 : 0; } From patchwork Wed Mar 6 07:13:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052151 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="palcvo3c"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlRL4Yshz9sMx for ; Wed, 6 Mar 2019 18:15:58 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729348AbfCFHPx (ORCPT ); Wed, 6 Mar 2019 02:15:53 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:57468 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729239AbfCFHOc (ORCPT ); Wed, 6 Mar 2019 02:14:32 -0500 Received: from pps.filterd (m0001255.ppops.net [127.0.0.1]) by mx0b-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267Ce4M007454 for ; Tue, 5 Mar 2019 23:14:31 -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=YD+fcm/fusDClh4H7LLxV82JlUR6M6cXHEgXwK9hXPY=; b=palcvo3cBrwSUD3NV+8gD+hIC9D8T3DdRuMshGRiRWyn7EzvY4olXyf3aibc4tgQltx0 xyCa31ISzlH/uiEQIB0ckwDry13px7o7Xlhnpjucsc/GQTOS0d0Vq7YUUDZ/qMQ4k7+R geonecCmI/bQSIOXKN04Qlhey97iNib6gV8= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0b-00082601.pphosted.com with ESMTP id 2r2861g6aq-9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:31 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::127) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:19 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 1EC1E62E2965; Tue, 5 Mar 2019 23:14:18 -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 v6 perf, bpf 05/15] perf: change prototype of perf_event__synthesize_bpf_events() Date: Tue, 5 Mar 2019 23:13:49 -0800 Message-ID: <20190306071359.2359896-6-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch changes the arguments of perf_event__synthesize_bpf_events() to include perf_session* instead of perf_tool*. perf_session will be used in the next patch. Signed-off-by: Song Liu --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/bpf-event.c | 8 +++++--- tools/perf/util/bpf-event.h | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 88ea11d57c6f..2355e0a9eda0 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1083,7 +1083,7 @@ static int record__synthesize(struct record *rec, bool tail) return err; } - err = perf_event__synthesize_bpf_events(tool, process_synthesized_event, + err = perf_event__synthesize_bpf_events(session, process_synthesized_event, machine, opts); if (err < 0) pr_warning("Couldn't synthesize bpf events.\n"); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 5a486d4de56e..27d8d42e0a4d 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1216,7 +1216,7 @@ static int __cmd_top(struct perf_top *top) init_process_thread(top); - ret = perf_event__synthesize_bpf_events(&top->tool, perf_event__process, + ret = perf_event__synthesize_bpf_events(top->session, perf_event__process, &top->session->machines.host, &top->record_opts); if (ret < 0) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index e6dfb95029e5..ff7ee149ec46 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -10,6 +10,7 @@ #include "debug.h" #include "symbol.h" #include "machine.h" +#include "session.h" #define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr)) @@ -42,7 +43,7 @@ int machine__process_bpf_event(struct machine *machine __maybe_unused, * -1 for failures; * -2 for lack of kernel support. */ -static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, +static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, perf_event__handler_t process, struct machine *machine, int fd, @@ -52,6 +53,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, struct ksymbol_event *ksymbol_event = &event->ksymbol_event; struct bpf_event *bpf_event = &event->bpf_event; struct bpf_prog_info_linear *info_linear; + struct perf_tool *tool = session->tool; struct bpf_prog_info *info; struct btf *btf = NULL; bool has_btf = false; @@ -175,7 +177,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, return err ? -1 : 0; } -int perf_event__synthesize_bpf_events(struct perf_tool *tool, +int perf_event__synthesize_bpf_events(struct perf_session *session, perf_event__handler_t process, struct machine *machine, struct record_opts *opts) @@ -209,7 +211,7 @@ int perf_event__synthesize_bpf_events(struct perf_tool *tool, continue; } - err = perf_event__synthesize_one_bpf_prog(tool, process, + err = perf_event__synthesize_one_bpf_prog(session, process, machine, fd, event, opts); close(fd); diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index 7890067e1a37..6698683612a7 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -15,7 +15,7 @@ struct record_opts; int machine__process_bpf_event(struct machine *machine, union perf_event *event, struct perf_sample *sample); -int perf_event__synthesize_bpf_events(struct perf_tool *tool, +int perf_event__synthesize_bpf_events(struct perf_session *session, perf_event__handler_t process, struct machine *machine, struct record_opts *opts); @@ -27,7 +27,7 @@ static inline int machine__process_bpf_event(struct machine *machine __maybe_unu return 0; } -static inline int perf_event__synthesize_bpf_events(struct perf_tool *tool __maybe_unused, +static inline int perf_event__synthesize_bpf_events(struct perf_session *session __maybe_unused, perf_event__handler_t process __maybe_unused, struct machine *machine __maybe_unused, struct record_opts *opts __maybe_unused) From patchwork Wed Mar 6 07:13:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052150 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="IcTJn1Qm"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlR42Ys5z9s1B for ; Wed, 6 Mar 2019 18:15:44 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729071AbfCFHPm (ORCPT ); Wed, 6 Mar 2019 02:15:42 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:57482 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729260AbfCFHOd (ORCPT ); Wed, 6 Mar 2019 02:14:33 -0500 Received: from pps.filterd (m0001255.ppops.net [127.0.0.1]) by mx0b-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267Ce4R007454 for ; Tue, 5 Mar 2019 23:14:32 -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=/4G2qHfT5nvvqHml+ZPq0wMYGt51ZXF51ny/oS8jfws=; b=IcTJn1QmXW10Os8PGCJDrJGXXvf+gO7V0cjibnnHuNcpg7mPyX3D4SMRggcDxUyLm4VY pLs0PRvO0R4Z/qm33oEFmmQOOHT7/D9JMTOZwMKSPYgTjeQ+5jl7RmG1/4Ki00jyqcRe TQ90EcOf3G2ADNXYJvM0Pq86z63LAY5lTj4= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0b-00082601.pphosted.com with ESMTP id 2r2861g6aq-14 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:32 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::127) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:20 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 34DCD62E2965; Tue, 5 Mar 2019 23:14:20 -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 v6 perf, bpf 06/15] perf, bpf: save bpf_prog_info in a rbtree in perf_env Date: Tue, 5 Mar 2019 23:13:50 -0800 Message-ID: <20190306071359.2359896-7-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org bpf_prog_info contains information necessary to annotate bpf programs. This patch saves bpf_prog_info for bpf programs loaded in the system. Some big picture of the next few patches: To fully annotate BPF programs with source code mapping, 4 different information are needed: 1) PERF_RECORD_KSYMBOL 2) PERF_RECORD_BPF_EVENT 3) bpf_prog_info 4) btf Before this set, 1) and 2) in the list are already saved to perf.data file. For BPF programs that are already loaded before perf run, 1) and 2) are synthesized by perf_event__synthesize_bpf_events(). For short living BPF programs, 1) and 2) are generated by kernel. This set handles 3) and 4) from the list. Again, it is necessary to handle existing BPF program and short living program separately. This patch handles 3) for exising BPF programs while synthesizing 1) and 2) in perf_event__synthesize_bpf_events(). These data are stored in perf_env. The next patch saves these data from perf_env to perf.data as headers. Similarly, the two patches after the next saves 4) of existing BPF programs to perf_env and perf.data. Another patch later will handle 3) and 4) for short living BPF programs by monitoring 1) and 2) in a dedicate thread. Signed-off-by: Song Liu --- tools/perf/perf.c | 1 + tools/perf/util/bpf-event.c | 32 +++++++++++++- tools/perf/util/bpf-event.h | 7 +++- tools/perf/util/env.c | 84 +++++++++++++++++++++++++++++++++++++ tools/perf/util/env.h | 18 ++++++++ tools/perf/util/session.c | 1 + 6 files changed, 141 insertions(+), 2 deletions(-) diff --git a/tools/perf/perf.c b/tools/perf/perf.c index a11cb006f968..72df4b6fa36f 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -298,6 +298,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) use_pager = 1; commit_pager_choice(); + perf_env__init(&perf_env); perf_env__set_cmdline(&perf_env, argc, argv); status = p->fn(argc, argv); perf_config__exit(); diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index ff7ee149ec46..ce81b2c43a51 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -10,6 +10,7 @@ #include "debug.h" #include "symbol.h" #include "machine.h" +#include "env.h" #include "session.h" #define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr)) @@ -54,17 +55,28 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, struct bpf_event *bpf_event = &event->bpf_event; struct bpf_prog_info_linear *info_linear; struct perf_tool *tool = session->tool; + struct bpf_prog_info_node *info_node; struct bpf_prog_info *info; struct btf *btf = NULL; bool has_btf = false; + struct perf_env *env; u32 sub_prog_cnt, i; int err = 0; u64 arrays; + /* + * for perf-record and perf-report use header.env; + * otherwise, use global perf_env. + */ + env = session->data ? &session->header.env : &perf_env; + arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS; arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS; + arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS; + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; + arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; info_linear = bpf_program__get_prog_info_linear(fd, arrays); if (IS_ERR_OR_NULL(info_linear)) { @@ -153,8 +165,8 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, machine, process); } - /* Synthesize PERF_RECORD_BPF_EVENT */ if (opts->bpf_event) { + /* Synthesize PERF_RECORD_BPF_EVENT */ *bpf_event = (struct bpf_event){ .header = { .type = PERF_RECORD_BPF_EVENT, @@ -167,6 +179,24 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE); memset((void *)event + event->header.size, 0, machine->id_hdr_size); event->header.size += machine->id_hdr_size; + + /* save bpf_prog_info to env */ + info_node = malloc(sizeof(struct bpf_prog_info_node)); + + /* + * Do not bail out for !info_node, as we still want to + * call perf_tool__process_synth_event() + */ + if (info_node) { + info_node->info_linear = info_linear; + perf_env__insert_bpf_prog_info(env, info_node); + info_linear = NULL; + } + + /* + * process after saving bpf_prog_info to env, so that + * required information is ready for look up + */ err = perf_tool__process_synth_event(tool, event, machine, process); } diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index 6698683612a7..fad932f7404f 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -3,14 +3,19 @@ #define __PERF_BPF_EVENT_H #include +#include #include "event.h" struct machine; union perf_event; struct perf_sample; -struct perf_tool; struct record_opts; +struct bpf_prog_info_node { + struct bpf_prog_info_linear *info_linear; + struct rb_node rb_node; +}; + #ifdef HAVE_LIBBPF_SUPPORT int machine__process_bpf_event(struct machine *machine, union perf_event *event, struct perf_sample *sample); diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 4c23779e271a..cdda46f2633f 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -3,15 +3,93 @@ #include "env.h" #include "sane_ctype.h" #include "util.h" +#include "bpf-event.h" #include #include +#include struct perf_env perf_env; +void perf_env__insert_bpf_prog_info(struct perf_env *env, + struct bpf_prog_info_node *info_node) +{ + __u32 prog_id = info_node->info_linear->info.id; + struct bpf_prog_info_node *node; + struct rb_node *parent = NULL; + struct rb_node **p; + + down_write(&env->bpf_progs.lock); + p = &env->bpf_progs.infos.rb_node; + + while (*p != NULL) { + parent = *p; + node = rb_entry(parent, struct bpf_prog_info_node, rb_node); + if (prog_id < node->info_linear->info.id) { + p = &(*p)->rb_left; + } else if (prog_id > node->info_linear->info.id) { + p = &(*p)->rb_right; + } else { + pr_debug("duplicated bpf prog info %u\n", prog_id); + goto out; + } + } + + rb_link_node(&info_node->rb_node, parent, p); + rb_insert_color(&info_node->rb_node, &env->bpf_progs.infos); +out: + up_write(&env->bpf_progs.lock); +} + +struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, + __u32 prog_id) +{ + struct bpf_prog_info_node *node = NULL; + struct rb_node *n; + + down_read(&env->bpf_progs.lock); + n = env->bpf_progs.infos.rb_node; + + while (n) { + node = rb_entry(n, struct bpf_prog_info_node, rb_node); + if (prog_id < node->info_linear->info.id) + n = n->rb_left; + else if (prog_id > node->info_linear->info.id) + n = n->rb_right; + else + break; + } + + up_read(&env->bpf_progs.lock); + return node; +} + +/* purge data in bpf_progs.infos tree */ +static void perf_env__purge_bpf(struct perf_env *env) +{ + struct rb_root *root; + struct rb_node *next; + + down_write(&env->bpf_progs.lock); + + root = &env->bpf_progs.infos; + next = rb_first(root); + + while (next) { + struct bpf_prog_info_node *node; + + node = rb_entry(next, struct bpf_prog_info_node, rb_node); + next = rb_next(&node->rb_node); + rb_erase_init(&node->rb_node, root); + free(node); + } + up_write(&env->bpf_progs.lock); +} + void perf_env__exit(struct perf_env *env) { int i; + perf_env__purge_bpf(env); zfree(&env->hostname); zfree(&env->os_release); zfree(&env->version); @@ -38,6 +116,12 @@ void perf_env__exit(struct perf_env *env) zfree(&env->memory_nodes); } +void perf_env__init(struct perf_env *env) +{ + env->bpf_progs.infos = RB_ROOT; + init_rwsem(&env->bpf_progs.lock); +} + int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) { int i; diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index d01b8355f4ca..e034e5b438e3 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -3,7 +3,9 @@ #define __PERF_ENV_H #include +#include #include "cpumap.h" +#include "rwsem.h" struct cpu_topology_map { int socket_id; @@ -64,8 +66,19 @@ struct perf_env { struct memory_node *memory_nodes; unsigned long long memory_bsize; u64 clockid_res_ns; + + /* + * bpf_info_lock protects bpf rbtrees. This is needed because the + * trees are accessed by different threads in perf-top + */ + struct { + struct rw_semaphore lock; + struct rb_root infos; + } bpf_progs; }; +struct bpf_prog_info_node; + extern struct perf_env perf_env; void perf_env__exit(struct perf_env *env); @@ -80,4 +93,9 @@ const char *perf_env__arch(struct perf_env *env); const char *perf_env__raw_arch(struct perf_env *env); int perf_env__nr_cpus_avail(struct perf_env *env); +void perf_env__init(struct perf_env *env); +void perf_env__insert_bpf_prog_info(struct perf_env *env, + struct bpf_prog_info_node *info_node); +struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, + __u32 prog_id); #endif /* __PERF_ENV_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 026bf04bba74..3c858f1b254e 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -129,6 +129,7 @@ struct perf_session *perf_session__new(struct perf_data *data, ordered_events__init(&session->ordered_events, ordered_events__deliver_event, NULL); + perf_env__init(&session->header.env); if (data) { if (perf_data__open(data)) goto out_delete; From patchwork Wed Mar 6 07:13:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052152 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="JDTM7RyU"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlRP5gx7z9s9T for ; Wed, 6 Mar 2019 18:16:01 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729234AbfCFHOa (ORCPT ); Wed, 6 Mar 2019 02:14:30 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:54946 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729212AbfCFHOY (ORCPT ); Wed, 6 Mar 2019 02:14:24 -0500 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267CjEd004881 for ; Tue, 5 Mar 2019 23:14:23 -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=/uzb11J9SR7fqpA2Lq6GyML7Mj2JiZ+JgZ9bFAeG+h8=; b=JDTM7RyUH93tdQ0R+EHLooBV4ce4D7xVaIZGGc/uDwBIhHgjmTVJX2lrpz/5ZyWzsaUt ISFRHLRxtWSrT4pxORBRUq2yaiktPipfNih4HJg2yhTyWRnwTuwhB3dOVI4Qntc5H3pU mlAnPQyAmG/JLMsTwDF/cccAP/Zzh0s0HmM= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r281ng70b-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:23 -0800 Received: from mx-out.facebook.com (2620:10d:c0a1:3::13) by mail.thefacebook.com (2620:10d:c021:18::174) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:22 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 3F49262E2965; Tue, 5 Mar 2019 23:14:22 -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 v6 perf, bpf 07/15] perf, bpf: save bpf_prog_info information as headers to perf.data Date: Tue, 5 Mar 2019 23:13:51 -0800 Message-ID: <20190306071359.2359896-8-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch enables perf-record to save bpf_prog_info information as headers to perf.data. A new header type HEADER_BPF_PROG_INFO is introduced for this data. Signed-off-by: Song Liu --- tools/perf/util/header.c | 149 ++++++++++++++++++++++++++++++++++++++- tools/perf/util/header.h | 1 + 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4b88de5e9192..cd19b7891db7 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "evlist.h" #include "evsel.h" @@ -39,6 +40,7 @@ #include "tool.h" #include "time-utils.h" #include "units.h" +#include "bpf-event.h" #include "sane_ctype.h" @@ -1074,6 +1076,54 @@ static int write_clockid(struct feat_fd *ff, sizeof(ff->ph->env.clockid_res_ns)); } +static int write_bpf_prog_info(struct feat_fd *ff, + struct perf_evlist *evlist __maybe_unused) +{ + struct perf_env *env = &ff->ph->env; + struct rb_root *root; + struct rb_node *next; + u32 count = 0; + int ret; + + down_read(&env->bpf_progs.lock); + + root = &env->bpf_progs.infos; + next = rb_first(root); + while (next) { + ++count; + next = rb_next(next); + } + + ret = do_write(ff, &count, sizeof(count)); + if (ret < 0) + goto out; + + next = rb_first(root); + while (next) { + struct bpf_prog_info_node *node; + size_t len; + + node = rb_entry(next, struct bpf_prog_info_node, rb_node); + next = rb_next(&node->rb_node); + len = sizeof(struct bpf_prog_info_linear) + + node->info_linear->data_len; + + /* before writing to file, translate address to offset */ + bpf_program__bpil_addr_to_offs(node->info_linear); + ret = do_write(ff, node->info_linear, len); + /* + * translate back to address even when do_write() fails, + * so that this function never changes the data. + */ + bpf_program__bpil_offs_to_addr(node->info_linear); + if (ret < 0) + goto out; + } +out: + up_read(&env->bpf_progs.lock); + return ret; +} + static int cpu_cache_level__sort(const void *a, const void *b) { struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a; @@ -1554,6 +1604,29 @@ static void print_clockid(struct feat_fd *ff, FILE *fp) ff->ph->env.clockid_res_ns * 1000); } +static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp) +{ + struct perf_env *env = &ff->ph->env; + struct rb_root *root; + struct rb_node *next; + + down_read(&env->bpf_progs.lock); + + root = &env->bpf_progs.infos; + next = rb_first(root); + + while (next) { + struct bpf_prog_info_node *node; + + node = rb_entry(next, struct bpf_prog_info_node, rb_node); + next = rb_next(&node->rb_node); + fprintf(fp, "# bpf_prog_info of id %u\n", + node->info_linear->info.id); + } + + up_read(&env->bpf_progs.lock); +} + static void free_event_desc(struct perf_evsel *events) { struct perf_evsel *evsel; @@ -2586,6 +2659,79 @@ static int process_clockid(struct feat_fd *ff, return 0; } +static int process_bpf_prog_info(struct feat_fd *ff, + void *data __maybe_unused) +{ + struct bpf_prog_info_linear *info_linear; + struct bpf_prog_info_node *info_node; + struct perf_env *env = &ff->ph->env; + u32 count, i; + int err = -1; + + if (do_read_u32(ff, &count)) + return -1; + + if (ff->ph->needs_swap) + pr_warning("interpreting bpf_prog_info from systems with endianity is not yet supported\n"); + + down_write(&env->bpf_progs.lock); + + for (i = 0; i < count; ++i) { + u32 info_len, data_len; + + info_linear = NULL; + info_node = NULL; + if (do_read_u32(ff, &info_len)) + goto out; + if (do_read_u32(ff, &data_len)) + goto out; + + if (info_len > sizeof(struct bpf_prog_info)) { + pr_warning("detected invalid bpf_prog_info\n"); + goto out; + } + + info_linear = malloc(sizeof(struct bpf_prog_info_linear) + + data_len); + if (!info_linear) + goto out; + info_linear->info_len = sizeof(struct bpf_prog_info); + info_linear->data_len = data_len; + if (do_read_u64(ff, (u64 *)(&info_linear->arrays))) + goto out; + if (__do_read(ff, &info_linear->info, info_len)) + goto out; + if (info_len < sizeof(struct bpf_prog_info)) + memset(((void *)(&info_linear->info)) + info_len, 0, + sizeof(struct bpf_prog_info) - info_len); + + if (__do_read(ff, info_linear->data, data_len)) + goto out; + + /* endian mismatch, drop the info, continue */ + if (ff->ph->needs_swap) { + free(info_linear); + continue; + } + + info_node = malloc(sizeof(struct bpf_prog_info_node)); + if (!info_node) + goto out; + + /* after reading from file, translate offset to address */ + bpf_program__bpil_offs_to_addr(info_linear); + info_node->info_linear = info_linear; + perf_env__insert_bpf_prog_info(env, info_node); + } + + return 0; +out: + free(info_linear); + free(info_node); + up_write(&env->bpf_progs.lock); + return err; +} + struct feature_ops { int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); void (*print)(struct feat_fd *ff, FILE *fp); @@ -2645,7 +2791,8 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { FEAT_OPN(CACHE, cache, true), FEAT_OPR(SAMPLE_TIME, sample_time, false), FEAT_OPR(MEM_TOPOLOGY, mem_topology, true), - FEAT_OPR(CLOCKID, clockid, false) + FEAT_OPR(CLOCKID, clockid, false), + FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false) }; struct header_print_data { diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 0d553ddca0a3..0785c91b4c3a 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -39,6 +39,7 @@ enum { HEADER_SAMPLE_TIME, HEADER_MEM_TOPOLOGY, HEADER_CLOCKID, + HEADER_BPF_PROG_INFO, HEADER_LAST_FEATURE, HEADER_FEAT_BITS = 256, }; From patchwork Wed Mar 6 07:13:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052149 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="p6NMKOn1"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlQp4k4Rz9s1B for ; Wed, 6 Mar 2019 18:15:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728957AbfCFHP3 (ORCPT ); Wed, 6 Mar 2019 02:15:29 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:39390 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729252AbfCFHOf (ORCPT ); Wed, 6 Mar 2019 02:14:35 -0500 Received: from pps.filterd (m0148460.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267DwKE003879 for ; Tue, 5 Mar 2019 23:14:33 -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=hr8uwX4+bIMF/fgSZXlhqmuNaV8ARRG+U0H8UBZlNmE=; b=p6NMKOn1IMum5AxtysQtYG9/UauGKhtahcOt0K0ZVozZvExfc2wWscYSaBbBChEMsK9+ 03+elKBRW77WLOXmsoWgZBV2NiYmL94JNTBW1iN6IjAV+FdPOJ2HWPMC0C6pOwJmiR6a dIXeimKW9/IIRnDv03djW6aBul/NEDApKDQ= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r28v8r3bs-9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:33 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::129) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:25 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 611F162E2965; Tue, 5 Mar 2019 23:14:24 -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 v6 perf, bpf 08/15] perf, bpf: save btf in a rbtree in perf_env Date: Tue, 5 Mar 2019 23:13:52 -0800 Message-ID: <20190306071359.2359896-9-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org btf contains information necessary to annotate bpf programs. This patch saves btf for bpf programs loaded in the system. Signed-off-by: Song Liu --- tools/perf/util/bpf-event.c | 23 +++++++++++++ tools/perf/util/bpf-event.h | 7 ++++ tools/perf/util/env.c | 65 +++++++++++++++++++++++++++++++++++++ tools/perf/util/env.h | 4 +++ 4 files changed, 99 insertions(+) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index ce81b2c43a51..536ca95df5f4 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -34,6 +34,28 @@ int machine__process_bpf_event(struct machine *machine __maybe_unused, return 0; } +static int perf_env__fetch_btf(struct perf_env *env, + u32 btf_id, + struct btf *btf) +{ + struct btf_node *node; + u32 data_size; + const void *data; + + data = btf__get_raw_data(btf, &data_size); + + node = malloc(data_size + sizeof(struct btf_node)); + if (!node) + return -1; + + node->id = btf_id; + node->data_size = data_size; + memcpy(node->data, data, data_size); + + perf_env__insert_btf(env, node); + return 0; +} + /* * Synthesize PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT for one bpf * program. One PERF_RECORD_BPF_EVENT is generated for the program. And @@ -113,6 +135,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, goto out; } has_btf = true; + perf_env__fetch_btf(env, info->btf_id, btf); } /* Synthesize PERF_RECORD_KSYMBOL */ diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index fad932f7404f..b9ec394dc7c7 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -16,6 +16,13 @@ struct bpf_prog_info_node { struct rb_node rb_node; }; +struct btf_node { + struct rb_node rb_node; + u32 id; + u32 data_size; + char data[]; +}; + #ifdef HAVE_LIBBPF_SUPPORT int machine__process_bpf_event(struct machine *machine, union perf_event *event, struct perf_sample *sample); diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index cdda46f2633f..9e4ee7b0a3d1 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -63,6 +63,57 @@ struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, return node; } +void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) +{ + struct rb_node *parent = NULL; + __u32 btf_id = btf_node->id; + struct btf_node *node; + struct rb_node **p; + + down_write(&env->bpf_progs.lock); + p = &env->bpf_progs.btfs.rb_node; + + while (*p != NULL) { + parent = *p; + node = rb_entry(parent, struct btf_node, rb_node); + if (btf_id < node->id) { + p = &(*p)->rb_left; + } else if (btf_id > node->id) { + p = &(*p)->rb_right; + } else { + pr_debug("duplicated btf %u\n", btf_id); + goto out; + } + } + + rb_link_node(&btf_node->rb_node, parent, p); + rb_insert_color(&btf_node->rb_node, &env->bpf_progs.btfs); +out: + up_write(&env->bpf_progs.lock); +} + +struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id) +{ + struct btf_node *node = NULL; + struct rb_node *n; + + down_read(&env->bpf_progs.lock); + n = env->bpf_progs.btfs.rb_node; + + while (n) { + node = rb_entry(n, struct btf_node, rb_node); + if (btf_id < node->id) + n = n->rb_left; + else if (btf_id > node->id) + n = n->rb_right; + else + break; + } + + up_read(&env->bpf_progs.lock); + return node; +} + /* purge data in bpf_progs.infos tree */ static void perf_env__purge_bpf(struct perf_env *env) { @@ -82,6 +133,19 @@ static void perf_env__purge_bpf(struct perf_env *env) rb_erase_init(&node->rb_node, root); free(node); } + + root = &env->bpf_progs.btfs; + next = rb_first(root); + + while (next) { + struct btf_node *node; + + node = rb_entry(next, struct btf_node, rb_node); + next = rb_next(&node->rb_node); + rb_erase_init(&node->rb_node, root); + free(node); + } + up_write(&env->bpf_progs.lock); } @@ -119,6 +183,7 @@ void perf_env__exit(struct perf_env *env) void perf_env__init(struct perf_env *env) { env->bpf_progs.infos = RB_ROOT; + env->bpf_progs.btfs = RB_ROOT; init_rwsem(&env->bpf_progs.lock); } diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index e034e5b438e3..c3e48504e834 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h @@ -74,10 +74,12 @@ struct perf_env { struct { struct rw_semaphore lock; struct rb_root infos; + struct rb_root btfs; } bpf_progs; }; struct bpf_prog_info_node; +struct btf_node; extern struct perf_env perf_env; @@ -98,4 +100,6 @@ void perf_env__insert_bpf_prog_info(struct perf_env *env, struct bpf_prog_info_node *info_node); struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, __u32 prog_id); +void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); +struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id); #endif /* __PERF_ENV_H */ From patchwork Wed Mar 6 07:13:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052143 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="mF6DyvXK"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlPv3SQkz9sMx for ; Wed, 6 Mar 2019 18:14:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729327AbfCFHOl (ORCPT ); Wed, 6 Mar 2019 02:14:41 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:39434 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729307AbfCFHOj (ORCPT ); Wed, 6 Mar 2019 02:14:39 -0500 Received: from pps.filterd (m0148460.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267DwKQ003879 for ; Tue, 5 Mar 2019 23:14:38 -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=H07Rsv1mfqop++Zt7ir99NMVXUl4go7yGnYElvtJRXs=; b=mF6DyvXK2v4i4dh4w9irWE2C/arh1rL081jIHEAH2AkFSDu440HDMMx6dfFffTmTmNtQ aQmk7Ps1PzsfyzqY7IJn4e/Iov8uuYl6duyTwMMR95YHtOZ1Jvsmn4/R0Zaj8bt81POd CLA2kGlDOs4GaK3eXZJL5yruPuVZVQ/bbkk= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r28v8r3bs-20 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:37 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::129) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:28 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 34A0E62E2965; Tue, 5 Mar 2019 23:14:26 -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 v6 perf, bpf 09/15] perf, bpf: save btf information as headers to perf.data Date: Tue, 5 Mar 2019 23:13:53 -0800 Message-ID: <20190306071359.2359896-10-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch enables perf-record to save btf information as headers to perf.data A new header type HEADER_BPF_BTF is introduced for this data. Signed-off-by: Song Liu --- tools/perf/util/header.c | 111 ++++++++++++++++++++++++++++++++++++++- tools/perf/util/header.h | 1 + 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index cd19b7891db7..1a329da6011b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1124,6 +1124,45 @@ static int write_bpf_prog_info(struct feat_fd *ff, return ret; } +static int write_bpf_btf(struct feat_fd *ff, + struct perf_evlist *evlist __maybe_unused) +{ + struct perf_env *env = &ff->ph->env; + struct rb_root *root; + struct rb_node *next; + u32 count = 0; + int ret; + + down_read(&env->bpf_progs.lock); + + root = &env->bpf_progs.btfs; + next = rb_first(root); + while (next) { + ++count; + next = rb_next(next); + } + + ret = do_write(ff, &count, sizeof(count)); + + if (ret < 0) + goto out; + + next = rb_first(root); + while (next) { + struct btf_node *node; + + node = rb_entry(next, struct btf_node, rb_node); + next = rb_next(&node->rb_node); + ret = do_write(ff, &node->id, + sizeof(u32) * 2 + node->data_size); + if (ret < 0) + goto out; + } +out: + up_read(&env->bpf_progs.lock); + return ret; +} + static int cpu_cache_level__sort(const void *a, const void *b) { struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a; @@ -1627,6 +1666,28 @@ static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp) up_read(&env->bpf_progs.lock); } +static void print_bpf_btf(struct feat_fd *ff, FILE *fp) +{ + struct perf_env *env = &ff->ph->env; + struct rb_root *root; + struct rb_node *next; + + down_read(&env->bpf_progs.lock); + + root = &env->bpf_progs.btfs; + next = rb_first(root); + + while (next) { + struct btf_node *node; + + node = rb_entry(next, struct btf_node, rb_node); + next = rb_next(&node->rb_node); + fprintf(fp, "# btf info of id %u\n", node->id); + } + + up_read(&env->bpf_progs.lock); +} + static void free_event_desc(struct perf_evsel *events) { struct perf_evsel *evsel; @@ -2732,6 +2793,53 @@ static int process_bpf_prog_info(struct feat_fd *ff, return err; } +static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused) +{ + struct perf_env *env = &ff->ph->env; + u32 count, i; + + if (do_read_u32(ff, &count)) + return -1; + + if (ff->ph->needs_swap) + pr_warning("interpreting btf from systems with endianity is not yet supported\n"); + + down_write(&env->bpf_progs.lock); + + for (i = 0; i < count; ++i) { + struct btf_node *node; + u32 id, data_size; + + if (do_read_u32(ff, &id)) + return -1; + if (do_read_u32(ff, &data_size)) + return -1; + + node = malloc(sizeof(struct btf_node) + data_size); + if (!node) + return -1; + + node->id = id; + node->data_size = data_size; + + if (__do_read(ff, node->data, data_size)) { + free(node); + return -1; + } + + /* endian mismatch, drop the btf, continue */ + if (ff->ph->needs_swap) { + free(node); + continue; + } + + perf_env__insert_btf(env, node); + } + + up_write(&env->bpf_progs.lock); + return 0; +} + struct feature_ops { int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); void (*print)(struct feat_fd *ff, FILE *fp); @@ -2792,7 +2900,8 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { FEAT_OPR(SAMPLE_TIME, sample_time, false), FEAT_OPR(MEM_TOPOLOGY, mem_topology, true), FEAT_OPR(CLOCKID, clockid, false), - FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false) + FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false), + FEAT_OPR(BPF_BTF, bpf_btf, false) }; struct header_print_data { diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 0785c91b4c3a..9e7d931f7c0d 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -40,6 +40,7 @@ enum { HEADER_MEM_TOPOLOGY, HEADER_CLOCKID, HEADER_BPF_PROG_INFO, + HEADER_BPF_BTF, HEADER_LAST_FEATURE, HEADER_FEAT_BITS = 256, }; From patchwork Wed Mar 6 07:13:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052142 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="Ed0hf3J6"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlPk5kVBz9sMx for ; Wed, 6 Mar 2019 18:14:34 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729259AbfCFHOd (ORCPT ); Wed, 6 Mar 2019 02:14:33 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:54970 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729229AbfCFHOa (ORCPT ); Wed, 6 Mar 2019 02:14:30 -0500 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267Cj9m004878 for ; Tue, 5 Mar 2019 23:14:29 -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=v4CFG6GAoKDdVvUtX74CjwljSMlGo1gNsqjCsZJtPw0=; b=Ed0hf3J6yS3TmhNnnuQ0NJIHwUcfab2c0zgber22VyASaimRe4vok/z8bx1uPuAeOnMk IfAvsckXqbxql+sMA7i0jmvT0cRmJV7aFc60R9FBnEstlXR0V1mRrseEPoAOpFL/flFl +fKs3lcEnJ5XonYhAuU8+FU93fuERdGFB2Y= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r281ng70g-8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:29 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::126) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:28 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 3B05962E2965; Tue, 5 Mar 2019 23:14:28 -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 v6 perf,bpf 10/15] perf-top: add option --no-bpf-event Date: Tue, 5 Mar 2019 23:13:54 -0800 Message-ID: <20190306071359.2359896-11-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org bpf events should be tracked by default for perf-top. This patch makes it on by default, and adds option to disable bpf events. Signed-off-by: Song Liu --- tools/perf/builtin-top.c | 3 +++ tools/perf/util/top.h | 1 + 2 files changed, 4 insertions(+) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 27d8d42e0a4d..ccdf5689452f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1492,6 +1492,7 @@ int cmd_top(int argc, const char **argv) "Display raw encoding of assembly instructions (default)"), OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, "Enable kernel symbol demangling"), + OPT_BOOLEAN(0, "no-bpf-event", &top.no_bpf_event, "do not record bpf events"), OPT_STRING(0, "objdump", &top.annotation_opts.objdump_path, "path", "objdump binary to use for disassembly and annotations"), OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style", @@ -1651,6 +1652,8 @@ int cmd_top(int argc, const char **argv) signal(SIGWINCH, winch_sig); } + top.record_opts.bpf_event = !top.no_bpf_event; + status = __cmd_top(&top); out_delete_evlist: diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 19f95eaf75c8..862a37bd27ea 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h @@ -32,6 +32,7 @@ struct perf_top { bool use_tui, use_stdio; bool vmlinux_warned; bool dump_symtab; + bool no_bpf_event; struct hist_entry *sym_filter_entry; struct perf_evsel *sym_evsel; struct perf_session *session; From patchwork Wed Mar 6 07:13:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052146 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="UGr7hx4d"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlQT0v4Xz9sBF for ; Wed, 6 Mar 2019 18:15:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729391AbfCFHPM (ORCPT ); Wed, 6 Mar 2019 02:15:12 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:42960 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729124AbfCFHPL (ORCPT ); Wed, 6 Mar 2019 02:15:11 -0500 Received: from pps.filterd (m0044012.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2674VCg014195 for ; Tue, 5 Mar 2019 23:15:10 -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=u0UUjGAvbLh2sH/TNv25fxNz2CmH4OKo+0+mXwfTh8I=; b=UGr7hx4d351ezST6MsTHmqDn8TVopPQ7YILlONZzEhdaLJR9+ZZ4uqfpafCKvkhrxzyX jpSQvPocTJnJv87TUTUTarLLyxHapXWWbwTaY+iHuCPsZ8PcqeiyPlc5aHCOnggYz/r6 ba1jjviuZFLm+y2B9+EvOf39jyS/opT5NRM= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r26fxretv-12 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:15:10 -0800 Received: from mx-out.facebook.com (2620:10d:c0a1:3::13) by mail.thefacebook.com (2620:10d:c021:18::174) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:30 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 6811562E2965; Tue, 5 Mar 2019 23:14:30 -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 v6 perf,bpf 11/15] perf: add -lopcodes to feature-libbfd Date: Tue, 5 Mar 2019 23:13:55 -0800 Message-ID: <20190306071359.2359896-12-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Both libbfd and libopcodes are distributed with binutil-dev/devel. When libbfd presents, it is OK to assume libopcodes also presents. This has been a safe assumption for bpftool. This patch adds -lopcodes to perf/Makefile.config. libopcodes will be used in the next commit for bpf annotation. Signed-off-by: Song Liu --- tools/perf/Makefile.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index b441c88cafa1..e0bafbc273af 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -701,7 +701,7 @@ else endif ifeq ($(feature-libbfd), 1) - EXTLIBS += -lbfd + EXTLIBS += -lbfd -lopcodes else # we are on a system that requires -liberty and (maybe) -lz # to link against -lbfd; test each case individually here From patchwork Wed Mar 6 07:13:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052148 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="ah3SX6lK"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlQg5t0Gz9s1B for ; Wed, 6 Mar 2019 18:15:23 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729287AbfCFHOh (ORCPT ); Wed, 6 Mar 2019 02:14:37 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:50502 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729271AbfCFHOg (ORCPT ); Wed, 6 Mar 2019 02:14:36 -0500 Received: from pps.filterd (m0148461.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267Cnpq015782 for ; Tue, 5 Mar 2019 23:14:35 -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=L17lMYCs4qCtCVnJBRZdUACuxGqR670uJ3oSj4rBavM=; b=ah3SX6lKuE6oTNHncT9T0hTHZW3oKVOxW5OohF3g3GckWolxTykrDQRH1TL/Z8vY/b/X ICDslYxIeowlboHJC7RYOCVyPMB61vJgwfBt+uEeBfa6PuCWrpEat7yl9BUWJnnpVmuc 9CfM/oyEe/cZ9ysmel8uHQV6ADhgSBX3NgU= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r29fag10g-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:35 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::126) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:34 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 8E53662E2965; Tue, 5 Mar 2019 23:14:32 -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 v6 perf, bpf 12/15] perf, bpf: enable annotation of bpf program Date: Tue, 5 Mar 2019 23:13:56 -0800 Message-ID: <20190306071359.2359896-13-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch enables the annotation of bpf program. A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso calls into a new function symbol__disassemble_bpf(), where annotation line information is filled based bpf_prog_info and btf saved in given perf_env. symbol__disassemble_bpf() uses libbfd to disassemble bpf programs. Signed-off-by: Song Liu --- tools/build/Makefile.feature | 6 +- tools/perf/Makefile.config | 4 + tools/perf/util/annotate.c | 150 ++++++++++++++++++++++++++++++++++- tools/perf/util/dso.c | 1 + tools/perf/util/dso.h | 33 +++++--- tools/perf/util/symbol.c | 1 + 6 files changed, 181 insertions(+), 14 deletions(-) diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 5467c6bf9ceb..4f35e9ff1e00 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -71,7 +71,8 @@ FEATURE_TESTS_BASIC := \ sdt \ setns \ libopencsd \ - libaio + libaio \ + disassembler-four-args # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests @@ -118,7 +119,8 @@ FEATURE_DISPLAY ?= \ lzma \ get_cpuid \ bpf \ - libaio + libaio \ + disassembler-four-args # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. # If in the future we need per-feature checks/flags for features not diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index e0bafbc273af..ab223239f1fb 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -796,6 +796,10 @@ ifdef HAVE_KVM_STAT_SUPPORT CFLAGS += -DHAVE_KVM_STAT_SUPPORT endif +ifeq ($(feature-disassembler-four-args), 1) + CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE +endif + ifeq (${IS_64_BIT}, 1) ifndef NO_PERF_READ_VDSO32 $(call feature_check,compile-32) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 70de8f6b3aee..e467aa0ef0c2 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -9,6 +9,10 @@ #include #include +#include +#include +#include +#include #include "util.h" #include "ui/ui.h" #include "sort.h" @@ -22,6 +26,7 @@ #include "annotate.h" #include "evsel.h" #include "evlist.h" +#include "bpf-event.h" #include "block-range.h" #include "string2.h" #include "arch/common.h" @@ -29,6 +34,9 @@ #include #include #include +#include +#include +#include /* FIXME: For the HE_COLORSET */ #include "ui/browser.h" @@ -1672,6 +1680,144 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil return 0; } +static int symbol__disassemble_bpf(struct symbol *sym, + struct annotate_args *args) +{ + struct annotation *notes = symbol__annotation(sym); + struct annotation_options *opts = args->options; + struct bpf_prog_info_linear *info_linear; + struct bpf_prog_linfo *prog_linfo = NULL; + struct bpf_prog_info_node *info_node; + int len = sym->end - sym->start; + disassembler_ftype disassemble; + struct map *map = args->ms.map; + struct disassemble_info info; + struct dso *dso = map->dso; + int pc = 0, count, sub_id; + struct btf *btf = NULL; + char tpath[PATH_MAX]; + size_t buf_size; + int nr_skip = 0; + int ret = -1; + char *buf; + bfd *bfdf; + FILE *s; + + if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO) + return -1; + + pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__, + sym->name, sym->start, sym->end - sym->start); + + memset(tpath, 0, sizeof(tpath)); + perf_exe(tpath, sizeof(tpath)); + + bfdf = bfd_openr(tpath, NULL); + assert(bfdf); + assert(bfd_check_format(bfdf, bfd_object)); + + s = open_memstream(&buf, &buf_size); + if (!s) + goto out; + init_disassemble_info(&info, s, + (fprintf_ftype) fprintf); + + info.arch = bfd_get_arch(bfdf); + info.mach = bfd_get_mach(bfdf); + + info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, + dso->bpf_prog.id); + if (!info_node) + goto out; + info_linear = info_node->info_linear; + sub_id = dso->bpf_prog.sub_id; + + info.buffer = (void *)(info_linear->info.jited_prog_insns); + info.buffer_length = info_linear->info.jited_prog_len; + + if (info_linear->info.nr_line_info) + prog_linfo = bpf_prog_linfo__new(&info_linear->info); + + if (info_linear->info.btf_id) { + struct btf_node *node; + + node = perf_env__find_btf(dso->bpf_prog.env, + info_linear->info.btf_id); + if (node) + btf = btf__new((__u8 *)(node->data), + node->data_size); + } + + disassemble_init_for_target(&info); + +#ifdef DISASM_FOUR_ARGS_SIGNATURE + disassemble = disassembler(info.arch, + bfd_big_endian(bfdf), + info.mach, + bfdf); +#else + disassemble = disassembler(bfdf); +#endif + assert(disassemble); + + fflush(s); + do { + const struct bpf_line_info *linfo = NULL; + struct disasm_line *dl; + size_t prev_buf_size; + const char *srcline; + u64 addr; + + addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id]; + count = disassemble(pc, &info); + + if (prog_linfo) + linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo, + addr, sub_id, + nr_skip); + + if (linfo && btf) { + srcline = btf__name_by_offset(btf, linfo->line_off); + nr_skip++; + } else + srcline = NULL; + + fprintf(s, "\n"); + prev_buf_size = buf_size; + fflush(s); + + if (!opts->hide_src_code && srcline) { + args->offset = -1; + args->line = strdup(srcline); + args->line_nr = 0; + args->ms.sym = sym; + dl = disasm_line__new(args); + if (dl) { + annotation_line__add(&dl->al, + ¬es->src->source); + } + } + + args->offset = pc; + args->line = buf + prev_buf_size; + args->line_nr = 0; + args->ms.sym = sym; + dl = disasm_line__new(args); + if (dl) + annotation_line__add(&dl->al, ¬es->src->source); + + pc += count; + } while (count > 0 && pc < len); + + ret = 0; +out: + free(prog_linfo); + free(btf); + fclose(s); + bfd_close(bfdf); + return ret; +} + static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) { struct annotation_options *opts = args->options; @@ -1699,7 +1845,9 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) pr_debug("annotating [%p] %30s : [%p] %30s\n", dso, dso->long_name, sym, sym->name); - if (dso__is_kcore(dso)) { + if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) { + return symbol__disassemble_bpf(sym, args); + } else if (dso__is_kcore(dso)) { kce.kcore_filename = symfs_filename; kce.addr = map__rip_2objdump(map, sym->start); kce.offs = sym->start; diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 62c8cf622607..1798192bf0f9 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -181,6 +181,7 @@ int dso__read_binary_type_filename(const struct dso *dso, case DSO_BINARY_TYPE__KALLSYMS: case DSO_BINARY_TYPE__GUEST_KALLSYMS: case DSO_BINARY_TYPE__JAVA_JIT: + case DSO_BINARY_TYPE__BPF_PROG_INFO: case DSO_BINARY_TYPE__NOT_FOUND: ret = -1; break; diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 8c8a7abe809d..f20d319463f1 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -14,6 +14,8 @@ #include "namespaces.h" #include "build-id.h" +struct perf_env; + enum dso_binary_type { DSO_BINARY_TYPE__KALLSYMS = 0, DSO_BINARY_TYPE__GUEST_KALLSYMS, @@ -34,6 +36,7 @@ enum dso_binary_type { DSO_BINARY_TYPE__KCORE, DSO_BINARY_TYPE__GUEST_KCORE, DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, + DSO_BINARY_TYPE__BPF_PROG_INFO, DSO_BINARY_TYPE__NOT_FOUND, }; @@ -177,17 +180,25 @@ struct dso { struct auxtrace_cache *auxtrace_cache; int comp; - /* dso data file */ - struct { - struct rb_root cache; - int fd; - int status; - u32 status_seen; - size_t file_size; - struct list_head open_entry; - u64 debug_frame_offset; - u64 eh_frame_hdr_offset; - } data; + union { + /* dso data file */ + struct { + struct rb_root cache; + int fd; + int status; + u32 status_seen; + size_t file_size; + struct list_head open_entry; + u64 debug_frame_offset; + u64 eh_frame_hdr_offset; + } data; + /* bpf prog information */ + struct { + u32 id; + u32 sub_id; + struct perf_env *env; + } bpf_prog; + }; union { /* Tool specific area */ void *priv; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 48efad6d0f90..33ae59e89da2 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1441,6 +1441,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod, case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO: return true; + case DSO_BINARY_TYPE__BPF_PROG_INFO: case DSO_BINARY_TYPE__NOT_FOUND: default: return false; From patchwork Wed Mar 6 07:13:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052147 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="ho1gpuys"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlQZ6w2Lz9s1B for ; Wed, 6 Mar 2019 18:15:18 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729392AbfCFHPS (ORCPT ); Wed, 6 Mar 2019 02:15:18 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:55034 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729275AbfCFHOh (ORCPT ); Wed, 6 Mar 2019 02:14:37 -0500 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267CjEg004881 for ; Tue, 5 Mar 2019 23:14:36 -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=p7J4kn/hqfIoQj6PwpRpZPCCrfLkkRibcLFLUhSZFlU=; b=ho1gpuysp2Yc8r58RNpno8rg4h1gK/16PDCE52Gs1IdgJM9ypIpHXkAtfq4nIvveXjeh uLHEL86HlLUsQ7bmHobZGotr7lAscX+gXIxplhKwjSPdcnONLtXSL009H/h2Y9+at31b A+c9cu7ww5JhHVNbWp7JV076fvHZPU3y20E= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r281ng70u-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:36 -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.1713.5; Tue, 5 Mar 2019 23:14:35 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 2D7F562E2965; Tue, 5 Mar 2019 23:14: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 v6 perf, bpf 13/15] perf, bpf: process PERF_BPF_EVENT_PROG_LOAD for annotation Date: Tue, 5 Mar 2019 23:13:57 -0800 Message-ID: <20190306071359.2359896-14-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds processing of PERF_BPF_EVENT_PROG_LOAD, which sets proper DSO type/id/etc of memory regions mapped to BPF programs to DSO_BINARY_TYPE__BPF_PROG_INFO Signed-off-by: Song Liu --- tools/perf/util/bpf-event.c | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 536ca95df5f4..9e3eae44c1d5 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -25,12 +25,65 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len) return ret; } +static int machine__process_bpf_event_load(struct machine *machine, + union perf_event *event, + struct perf_sample *sample __maybe_unused) +{ + struct bpf_prog_info_linear *info_linear; + struct bpf_prog_info_node *info_node; + struct perf_env *env = machine->env; + int id = event->bpf_event.id; + unsigned int i; + + /* perf-record, no need to handle bpf-event */ + if (env == NULL) + return 0; + + info_node = perf_env__find_bpf_prog_info(env, id); + if (!info_node) + return 0; + info_linear = info_node->info_linear; + + for (i = 0; i < info_linear->info.nr_jited_ksyms; i++) { + u64 *addrs = (u64 *)(info_linear->info.jited_ksyms); + u64 addr = addrs[i]; + struct map *map; + + map = map_groups__find(&machine->kmaps, addr); + + if (map) { + map->dso->binary_type = DSO_BINARY_TYPE__BPF_PROG_INFO; + map->dso->bpf_prog.id = id; + map->dso->bpf_prog.sub_id = i; + map->dso->bpf_prog.env = env; + } + } + return 0; +} + int machine__process_bpf_event(struct machine *machine __maybe_unused, union perf_event *event, struct perf_sample *sample __maybe_unused) { if (dump_trace) perf_event__fprintf_bpf_event(event, stdout); + + switch (event->bpf_event.type) { + case PERF_BPF_EVENT_PROG_LOAD: + return machine__process_bpf_event_load(machine, event, sample); + + case PERF_BPF_EVENT_PROG_UNLOAD: + /* + * Do not free bpf_prog_info and btf of the program here, + * as annotation still need them. They will be freed at + * the end of the session. + */ + break; + default: + pr_debug("unexpected bpf_event type of %d\n", + event->bpf_event.type); + break; + } return 0; } From patchwork Wed Mar 6 07:13:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052144 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="ZKutHJ5B"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlQC4FHDz9sBF for ; Wed, 6 Mar 2019 18:14:59 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729361AbfCFHOx (ORCPT ); Wed, 6 Mar 2019 02:14:53 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:35056 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729304AbfCFHOi (ORCPT ); Wed, 6 Mar 2019 02:14:38 -0500 Received: from pps.filterd (m0044008.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x267E0GF022045 for ; Tue, 5 Mar 2019 23:14:37 -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=+2bdhBCHoUTMvMJXVt2p1xLyY+Hq8xNP3KqJwt83FOw=; b=ZKutHJ5BO27zu4qXEIdF5z/V42EJrOjZume4urIQgSKDq0KCWBzpdJ9XHJFSoh4ZvTlU SU4dzVQE1tjHIFBiAD97fMMM/+PFKW3cBoLNEXYytKkIEpNtLa8+mzi//jAaVsZNfJrl DKQnDk4vg0vLpEazqkBCZBAII/WfcLR2PgQ= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r27j189w9-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:37 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::127) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:36 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id E1B6562E2965; Tue, 5 Mar 2019 23:14:35 -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 v6 perf,bpf 14/15] perf: introduce side band thread Date: Tue, 5 Mar 2019 23:13:58 -0800 Message-ID: <20190306071359.2359896-15-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch introduces side band thread that captures extended information for events like PERF_RECORD_BPF_EVENT. This new thread uses its own evlist that uses ring buffer with very low watermark for lower latency. To use side band thread, we need to: 1. add side band event(s) by calling perf_evlist__add_sb_event(); 2. calls perf_evlist__start_sb_thread(); 3. at the end of perf run, perf_evlist__stop_sb_thread(). In the next patch, we use this thread to handle PERF_RECORD_BPF_EVENT. Signed-off-by: Song Liu --- tools/perf/builtin-record.c | 5 ++ tools/perf/builtin-top.c | 5 ++ tools/perf/util/evlist.c | 113 ++++++++++++++++++++++++++++++++++++ tools/perf/util/evlist.h | 13 +++++ tools/perf/util/evsel.h | 6 ++ 5 files changed, 142 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 2355e0a9eda0..435b94f1f3b3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1106,6 +1106,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) struct perf_data *data = &rec->data; struct perf_session *session; bool disabled = false, draining = false; + struct perf_evlist *sb_evlist = NULL; int fd; atexit(record__sig_exit); @@ -1206,6 +1207,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_child; } + perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target); + err = record__synthesize(rec, false); if (err < 0) goto out_child; @@ -1456,6 +1459,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) out_delete_session: perf_session__delete(session); + + perf_evlist__stop_sb_thread(sb_evlist); return status; } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ccdf5689452f..ec69eb040933 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1524,6 +1524,7 @@ int cmd_top(int argc, const char **argv) "number of thread to run event synthesize"), OPT_END() }; + struct perf_evlist *sb_evlist = NULL; const char * const top_usage[] = { "perf top []", NULL @@ -1654,8 +1655,12 @@ int cmd_top(int argc, const char **argv) top.record_opts.bpf_event = !top.no_bpf_event; + perf_evlist__start_sb_thread(sb_evlist, target); + status = __cmd_top(&top); + perf_evlist__stop_sb_thread(sb_evlist); + out_delete_evlist: perf_evlist__delete(top.evlist); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 8c902276d4b4..a06a4f54b083 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -19,6 +19,7 @@ #include "debug.h" #include "units.h" #include "asm/bug.h" +#include "bpf-event.h" #include #include @@ -1841,3 +1842,115 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, } return leader; } + +int perf_evlist__add_sb_event(struct perf_evlist **evlist, + struct perf_event_attr *attr, + perf_evsel__sb_cb_t cb, + void *data) +{ + struct perf_evsel *evsel; + bool new_evlist = (*evlist) == NULL; + + if (*evlist == NULL) + *evlist = perf_evlist__new(); + if (*evlist == NULL) + return -1; + + if (!attr->sample_id_all) { + pr_warning("enabling sample_id_all for all side band events\n"); + attr->sample_id_all = 1; + } + + evsel = perf_evsel__new_idx(attr, (*evlist)->nr_entries); + if (!evsel) + goto out_err; + + evsel->side_band.cb = cb; + evsel->side_band.data = data; + perf_evlist__add(*evlist, evsel); + return 0; + +out_err: + if (new_evlist) { + perf_evlist__delete(*evlist); + *evlist = NULL; + } + return -1; +} + +static void *perf_evlist__poll_thread(void *arg) +{ + struct perf_evlist *evlist = arg; + int i; + + while (!(evlist->thread.done)) { + perf_evlist__poll(evlist, 1000); + + for (i = 0; i < evlist->nr_mmaps; i++) { + struct perf_mmap *map = &evlist->mmap[i]; + union perf_event *event; + + if (perf_mmap__read_init(map)) + continue; + while ((event = perf_mmap__read_event(map)) != NULL) { + struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event); + + if (evsel && evsel->side_band.cb) + evsel->side_band.cb(event, evsel->side_band.data); + else + pr_warning("cannot locate proper evsel for the side band event\n"); + + perf_mmap__consume(map); + } + perf_mmap__read_done(map); + } + } + return NULL; +} + +int perf_evlist__start_sb_thread(struct perf_evlist *evlist, + struct target *target) +{ + struct perf_evsel *counter; + + if (!evlist) + return 0; + + if (perf_evlist__create_maps(evlist, target)) + goto out_delete_evlist; + + evlist__for_each_entry(evlist, counter) { + if (perf_evsel__open(counter, evlist->cpus, + evlist->threads) < 0) + goto out_delete_evlist; + } + + if (perf_evlist__mmap(evlist, UINT_MAX)) + goto out_delete_evlist; + + evlist__for_each_entry(evlist, counter) { + if (perf_evsel__enable(counter)) + goto out_delete_evlist; + } + + evlist->thread.done = 0; + if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist)) + goto out_delete_evlist; + + return 0; + +out_delete_evlist: + perf_evlist__delete(evlist); + evlist = NULL; + return -1; +} + +void perf_evlist__stop_sb_thread(struct perf_evlist *evlist) +{ + if (!evlist) + return; + evlist->thread.done = 1; + pthread_join(evlist->thread.th, NULL); + perf_evlist__exit(evlist); + evlist = NULL; +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 868294491194..ed8cab1b7438 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -51,6 +51,11 @@ struct perf_evlist { struct perf_env *env; u64 first_sample_time; u64 last_sample_time; + struct { + pthread_t th; + struct perf_evsel *evsel; + volatile int done; + } thread; }; struct perf_evsel_str_handler { @@ -84,6 +89,14 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, int perf_evlist__add_dummy(struct perf_evlist *evlist); +int perf_evlist__add_sb_event(struct perf_evlist **evlist, + struct perf_event_attr *attr, + perf_evsel__sb_cb_t cb, + void *data); +int perf_evlist__start_sb_thread(struct perf_evlist *evlist, + struct target *target); +void perf_evlist__stop_sb_thread(struct perf_evlist *evlist); + int perf_evlist__add_newtp(struct perf_evlist *evlist, const char *sys, const char *name, void *handler); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 29c5eb68c44b..94232ba9acce 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -73,6 +73,8 @@ struct perf_evsel_config_term { struct perf_stat_evsel; +typedef int (perf_evsel__sb_cb_t)(union perf_event *event, void *data); + /** struct perf_evsel - event selector * * @evlist - evlist this evsel is in, if it is in one. @@ -151,6 +153,10 @@ struct perf_evsel { bool collect_stat; bool weak_group; const char *pmu_name; + struct { + perf_evsel__sb_cb_t *cb; + void *data; + } side_band; }; union u64_swap { From patchwork Wed Mar 6 07:13:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1052145 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="QphJyETR"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44DlQP5JlYz9sMx for ; Wed, 6 Mar 2019 18:15:09 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729351AbfCFHOw (ORCPT ); Wed, 6 Mar 2019 02:14:52 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:52310 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729329AbfCFHOo (ORCPT ); Wed, 6 Mar 2019 02:14:44 -0500 Received: from pps.filterd (m0044010.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2675Wk2025811 for ; Tue, 5 Mar 2019 23:14:43 -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=2b7pztNlD+DxP7MyDX0Ko2nxKUdUpgrkodyr15xzJf4=; b=QphJyETRSLzuSRvTVyEM+35J+glErYBtGJLL4npT3OX/47tdiOqZbQ2Z4jnh1OQqiBvu Q3AeE5obdMVewobtjFTogj0b1biomhk77gYEYDKwJKdJgMHi/cH71TXdrEtNc9wdvhWF U+rLVEiTIhIwXSwNPsqWxMqWgvkud5lpa90= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2r26pxrdhk-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 05 Mar 2019 23:14:43 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::128) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 5 Mar 2019 23:14:40 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 301F062E2965; Tue, 5 Mar 2019 23:14:38 -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 v6 perf, bpf 15/15] perf, bpf: save bpf_prog_info and btf of short living bpf programs Date: Tue, 5 Mar 2019 23:13:59 -0800 Message-ID: <20190306071359.2359896-16-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190306071359.2359896-1-songliubraving@fb.com> References: <20190306071359.2359896-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-06_04:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org To fully annotate BPF programs with source code mapping, 4 different information are needed: 1) PERF_RECORD_KSYMBOL 2) PERF_RECORD_BPF_EVENT 3) bpf_prog_info 4) btf This patch handles 3) and 4) for short living BPF programs. For timely process of these information, a dedicated event is added to the side band evlist. When PERF_RECORD_BPF_EVENT is received via the side band event, the polling thread gathers 3) and 4) vis sys_bpf and store them in perf_env. These information are saved to perf.data at the end of perf-record. Signed-off-by: Song Liu --- tools/perf/builtin-record.c | 2 + tools/perf/builtin-top.c | 2 + tools/perf/util/bpf-event.c | 95 +++++++++++++++++++++++++++++++++++++ tools/perf/util/bpf-event.h | 15 ++++++ 4 files changed, 114 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 435b94f1f3b3..8d197762a499 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1207,6 +1207,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_child; } + if (opts->bpf_event) + bpf_event__add_sb_event(&sb_evlist, &session->header.env); perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target); err = record__synthesize(rec, false); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ec69eb040933..0d0da834dd9d 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1655,6 +1655,8 @@ int cmd_top(int argc, const char **argv) top.record_opts.bpf_event = !top.no_bpf_event; + if (top.record_opts.bpf_event) + bpf_event__add_sb_event(&sb_evlist, &perf_env); perf_evlist__start_sb_thread(sb_evlist, target); status = __cmd_top(&top); diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 9e3eae44c1d5..78e85832c1b4 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -12,6 +12,7 @@ #include "machine.h" #include "env.h" #include "session.h" +#include "evlist.h" #define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr)) @@ -331,3 +332,97 @@ int perf_event__synthesize_bpf_events(struct perf_session *session, free(event); return err; } + +static void perf_env__add_bpf_info(struct perf_env *env, u32 id) +{ + struct bpf_prog_info_linear *info_linear; + struct bpf_prog_info_node *info_node; + struct btf *btf = NULL; + u64 arrays; + u32 btf_id; + int fd; + + fd = bpf_prog_get_fd_by_id(id); + if (fd < 0) + return; + + arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS; + arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; + arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS; + arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS; + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; + arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; + + info_linear = bpf_program__get_prog_info_linear(fd, arrays); + if (IS_ERR_OR_NULL(info_linear)) { + pr_debug("%s: failed to get BPF program info. aborting\n", __func__); + goto out; + } + + btf_id = info_linear->info.btf_id; + + info_node = malloc(sizeof(struct bpf_prog_info_node)); + if (info_node) { + info_node->info_linear = info_linear; + perf_env__insert_bpf_prog_info(env, info_node); + } else + free(info_linear); + + if (btf_id == 0) + goto out; + + if (btf__get_from_id(btf_id, &btf)) { + pr_debug("%s: failed to get BTF of id %u, aborting\n", + __func__, btf_id); + goto out; + } + perf_env__fetch_btf(env, btf_id, btf); + +out: + free(btf); + close(fd); +} + +static int bpf_event__sb_cb(union perf_event *event, void *data) +{ + struct perf_env *env = data; + + if (event->header.type != PERF_RECORD_BPF_EVENT) + return -1; + + switch (event->bpf_event.type) { + case PERF_BPF_EVENT_PROG_LOAD: + perf_env__add_bpf_info(env, event->bpf_event.id); + + case PERF_BPF_EVENT_PROG_UNLOAD: + /* + * Do not free bpf_prog_info and btf of the program here, + * as annotation still need them. They will be freed at + * the end of the session. + */ + break; + default: + pr_debug("unexpected bpf_event type of %d\n", + event->bpf_event.type); + break; + } + + return 0; +} + +int bpf_event__add_sb_event(struct perf_evlist **evlist, + struct perf_env *env) +{ + struct perf_event_attr attr = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_DUMMY, + .sample_id_all = 1, + .watermark = 1, + .bpf_event = 1, + .wakeup_watermark = 1, + .size = sizeof(attr), /* to capture ABI version */ + }; + + return perf_evlist__add_sb_event(evlist, &attr, bpf_event__sb_cb, env); +} diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index b9ec394dc7c7..249909c826e7 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -4,12 +4,17 @@ #include #include +#include +#include #include "event.h" struct machine; union perf_event; +struct perf_env; struct perf_sample; struct record_opts; +struct evlist; +struct target; struct bpf_prog_info_node { struct bpf_prog_info_linear *info_linear; @@ -31,6 +36,9 @@ int perf_event__synthesize_bpf_events(struct perf_session *session, perf_event__handler_t process, struct machine *machine, struct record_opts *opts); +int bpf_event__add_sb_event(struct perf_evlist **evlist, + struct perf_env *env); + #else static inline int machine__process_bpf_event(struct machine *machine __maybe_unused, union perf_event *event __maybe_unused, @@ -46,5 +54,12 @@ static inline int perf_event__synthesize_bpf_events(struct perf_session *session { return 0; } + +static int bpf_event__add_sb_event(struct perf_evlist **evlist __maybe_unused, + struct perf_env *env __maybe_unused) +{ + return 0; +} + #endif // HAVE_LIBBPF_SUPPORT #endif