From nobody Sun Jun 28 00:08:49 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 773A9C433EF for ; Thu, 17 Feb 2022 13:19:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240848AbiBQNTt (ORCPT ); Thu, 17 Feb 2022 08:19:49 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:41848 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233011AbiBQNTr (ORCPT ); Thu, 17 Feb 2022 08:19:47 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E7AB2AE714; Thu, 17 Feb 2022 05:19:32 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id AF3E061B53; Thu, 17 Feb 2022 13:19:31 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4464EC340E8; Thu, 17 Feb 2022 13:19:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1645103971; bh=mjItu8EXoybpFead9lQL+S9gR/JLNKvMKHR04zWTSDk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PWwUauMoOTYPJiFMJDUvDbFiqt3hmWHdKAKEWxHuyR102M90cstGcxpNy5lJkm3rb JxGYjErWupdlWw9OjRhGuWMIyk4ESJxMNBm4PMQC4ug2EZ+J6vG60+X1jeSVdJXyBT /xlqmU0XEFnQ73ncscG+uEmTcEqqXQdnNodN/ACse4TClNjy1xOZRA3AG4YmxpO+N7 DfWtdP2U0VUpz28A8Js5DnasIcoNXqh19DoDBkM1wPE4jzXokPNm/hotr2WqA1hWdI e66/8aAuZkFn/UwRyvkvnTTyFm487R85iXnd2ySjTJyYLLSUnpV56kLPNI70Lz5ed4 lAqsdHPYcuVQw== From: Jiri Olsa To: Arnaldo Carvalho de Melo Cc: Andrii Nakryiko , lkml , Peter Zijlstra , Ingo Molnar , Mark Rutland , Namhyung Kim , Alexander Shishkin , Ian Rogers , linux-perf-users@vger.kernel.org, bpf@vger.kernel.org Subject: [PATCH 1/3] perf tools: Remove bpf_program__set_priv/bpf_program__priv usage Date: Thu, 17 Feb 2022 14:19:14 +0100 Message-Id: <20220217131916.50615-2-jolsa@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220217131916.50615-1-jolsa@kernel.org> References: <20220217131916.50615-1-jolsa@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Both bpf_program__set_priv/bpf_program__priv are deprecated and will be eventually removed. Using hashmap to replace that functionality. Suggested-by: Andrii Nakryiko Signed-off-by: Jiri Olsa --- tools/perf/util/bpf-loader.c | 91 +++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index db61e09be585..ec27aab2bd36 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -26,6 +26,7 @@ #include "util.h" #include "llvm-utils.h" #include "c++/clang-c.h" +#include "hashmap.h" =20 #include =20 @@ -55,6 +56,7 @@ struct bpf_perf_object { }; =20 static LIST_HEAD(bpf_objects_list); +static struct hashmap *bpf_program_hash; =20 static struct bpf_perf_object * bpf_perf_object__next(struct bpf_perf_object *prev) @@ -173,6 +175,35 @@ struct bpf_object *bpf__prepare_load(const char *filen= ame, bool source) return obj; } =20 +static void +clear_prog_priv(const struct bpf_program *prog __maybe_unused, + void *_priv) +{ + struct bpf_prog_priv *priv =3D _priv; + + cleanup_perf_probe_events(&priv->pev, 1); + zfree(&priv->insns_buf); + zfree(&priv->type_mapping); + zfree(&priv->sys_name); + zfree(&priv->evt_name); + free(priv); +} + +static void bpf_program_hash_free(void) +{ + struct hashmap_entry *cur; + size_t bkt; + + if (!bpf_program_hash) + return; + + hashmap__for_each_entry(bpf_program_hash, cur, bkt) + clear_prog_priv(cur->key, cur->value); + + hashmap__free(bpf_program_hash); + bpf_program_hash =3D NULL; +} + void bpf__clear(void) { struct bpf_perf_object *perf_obj, *tmp; @@ -181,20 +212,48 @@ void bpf__clear(void) bpf__unprobe(perf_obj->obj); bpf_perf_object__close(perf_obj); } + + bpf_program_hash_free(); } =20 -static void -clear_prog_priv(struct bpf_program *prog __maybe_unused, - void *_priv) +static size_t ptr_hash(const void *__key, void *ctx __maybe_unused) { - struct bpf_prog_priv *priv =3D _priv; + return (size_t) __key; +} =20 - cleanup_perf_probe_events(&priv->pev, 1); - zfree(&priv->insns_buf); - zfree(&priv->type_mapping); - zfree(&priv->sys_name); - zfree(&priv->evt_name); - free(priv); +static bool ptr_equal(const void *key1, const void *key2, + void *ctx __maybe_unused) +{ + return key1 =3D=3D key2; +} + +static void *program_priv(const struct bpf_program *prog) +{ + void *priv; + + if (!bpf_program_hash) + return NULL; + if (!hashmap__find(bpf_program_hash, prog, &priv)) + return NULL; + return priv; +} + +static int program_set_priv(struct bpf_program *prog, void *priv) +{ + void *old_priv; + + if (!bpf_program_hash) { + bpf_program_hash =3D hashmap__new(ptr_hash, ptr_equal, NULL); + if (!bpf_program_hash) + return -ENOMEM; + } + + old_priv =3D program_priv(prog); + if (old_priv) { + clear_prog_priv(prog, old_priv); + return hashmap__set(bpf_program_hash, prog, priv, NULL, NULL); + } + return hashmap__add(bpf_program_hash, prog, priv); } =20 static int @@ -438,7 +497,7 @@ config_bpf_program(struct bpf_program *prog) pr_debug("bpf: config '%s' is ok\n", config_str); =20 set_priv: - err =3D bpf_program__set_priv(prog, priv, clear_prog_priv); + err =3D program_set_priv(prog, priv); if (err) { pr_debug("Failed to set priv for program '%s'\n", config_str); goto errout; @@ -479,7 +538,7 @@ preproc_gen_prologue(struct bpf_program *prog, int n, struct bpf_insn *orig_insns, int orig_insns_cnt, struct bpf_prog_prep_result *res) { - struct bpf_prog_priv *priv =3D bpf_program__priv(prog); + struct bpf_prog_priv *priv =3D program_priv(prog); struct probe_trace_event *tev; struct perf_probe_event *pev; struct bpf_insn *buf; @@ -630,7 +689,7 @@ static int map_prologue(struct perf_probe_event *pev, i= nt *mapping, =20 static int hook_load_preprocessor(struct bpf_program *prog) { - struct bpf_prog_priv *priv =3D bpf_program__priv(prog); + struct bpf_prog_priv *priv =3D program_priv(prog); struct perf_probe_event *pev; bool need_prologue =3D false; int err, i; @@ -706,7 +765,7 @@ int bpf__probe(struct bpf_object *obj) if (err) goto out; =20 - priv =3D bpf_program__priv(prog); + priv =3D program_priv(prog); if (IS_ERR_OR_NULL(priv)) { if (!priv) err =3D -BPF_LOADER_ERRNO__INTERNAL; @@ -758,7 +817,7 @@ int bpf__unprobe(struct bpf_object *obj) struct bpf_program *prog; =20 bpf_object__for_each_program(prog, obj) { - struct bpf_prog_priv *priv =3D bpf_program__priv(prog); + struct bpf_prog_priv *priv =3D program_priv(prog); int i; =20 if (IS_ERR_OR_NULL(priv) || priv->is_tp) @@ -814,7 +873,7 @@ int bpf__foreach_event(struct bpf_object *obj, int err; =20 bpf_object__for_each_program(prog, obj) { - struct bpf_prog_priv *priv =3D bpf_program__priv(prog); + struct bpf_prog_priv *priv =3D program_priv(prog); struct probe_trace_event *tev; struct perf_probe_event *pev; int i, fd; --=20 2.35.1 From nobody Sun Jun 28 00:08:49 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DDBB2C433FE for ; Thu, 17 Feb 2022 13:19:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240862AbiBQNUA (ORCPT ); Thu, 17 Feb 2022 08:20:00 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:42050 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230451AbiBQNT6 (ORCPT ); Thu, 17 Feb 2022 08:19:58 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 92B672AED80; Thu, 17 Feb 2022 05:19:43 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 50224B82194; Thu, 17 Feb 2022 13:19:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63905C340E8; Thu, 17 Feb 2022 13:19:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1645103981; bh=UjT2kgD9baGmDbmhqizndkgeYds6jviLIAkYuMBbpMU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QCimiTFLnN2i7DKVexX5qAUICxFmZW+v5H6pJiNByIc/G/NGimCnSVGTLtMdN5O6U fiVKL6IDivQvDjohqL0KrAVhBPlFIV9pxwIu6uzFmoqQzSCU2enEvga5SLhtDll+PQ HOs+TGDc0177kjlAkBJLi8AH7+jph3YdcODGj4f1JlWKMFeF+M4yp957YuCtyokUek GrsWf9Qj8rGqS79EKRzfeLRMABHjWJfICw6BeZxC8y5Hu0G6bQqkeS4vZy/GqZ2/YL 9EEDSap9oebPjc7O1ora1KLXdaCIbmTerszRG9fC59yoJXvf3lXuHO7gPcS2K1egMU kwJzSDyS5podA== From: Jiri Olsa To: Arnaldo Carvalho de Melo Cc: Andrii Nakryiko , lkml , Peter Zijlstra , Ingo Molnar , Mark Rutland , Namhyung Kim , Alexander Shishkin , Ian Rogers , linux-perf-users@vger.kernel.org, bpf@vger.kernel.org Subject: [PATCH 2/3] perf tools: Remove bpf_map__set_priv/bpf_map__priv usage Date: Thu, 17 Feb 2022 14:19:15 +0100 Message-Id: <20220217131916.50615-3-jolsa@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220217131916.50615-1-jolsa@kernel.org> References: <20220217131916.50615-1-jolsa@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Both bpf_map__set_priv/bpf_map__priv are deprecated and will be eventually removed. Using hashmap to replace that functionality. Suggested-by: Andrii Nakryiko Signed-off-by: Jiri Olsa --- tools/perf/util/bpf-loader.c | 62 ++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index ec27aab2bd36..6f87729817ad 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -57,6 +57,7 @@ struct bpf_perf_object { =20 static LIST_HEAD(bpf_objects_list); static struct hashmap *bpf_program_hash; +static struct hashmap *bpf_map_hash; =20 static struct bpf_perf_object * bpf_perf_object__next(struct bpf_perf_object *prev) @@ -204,6 +205,8 @@ static void bpf_program_hash_free(void) bpf_program_hash =3D NULL; } =20 +static void bpf_map_hash_free(void); + void bpf__clear(void) { struct bpf_perf_object *perf_obj, *tmp; @@ -214,6 +217,7 @@ void bpf__clear(void) } =20 bpf_program_hash_free(); + bpf_map_hash_free(); } =20 static size_t ptr_hash(const void *__key, void *ctx __maybe_unused) @@ -969,7 +973,7 @@ bpf_map_priv__purge(struct bpf_map_priv *priv) } =20 static void -bpf_map_priv__clear(struct bpf_map *map __maybe_unused, +bpf_map_priv__clear(const struct bpf_map *map __maybe_unused, void *_priv) { struct bpf_map_priv *priv =3D _priv; @@ -978,6 +982,50 @@ bpf_map_priv__clear(struct bpf_map *map __maybe_unused, free(priv); } =20 +static void *map_priv(const struct bpf_map *map) +{ + void *priv; + + if (!bpf_map_hash) + return NULL; + if (!hashmap__find(bpf_map_hash, map, &priv)) + return NULL; + return priv; +} + +static void bpf_map_hash_free(void) +{ + struct hashmap_entry *cur; + size_t bkt; + + if (!bpf_map_hash) + return; + + hashmap__for_each_entry(bpf_map_hash, cur, bkt) + bpf_map_priv__clear(cur->key, cur->value); + + hashmap__free(bpf_map_hash); + bpf_map_hash =3D NULL; +} + +static int map_set_priv(struct bpf_map *map, void *priv) +{ + void *old_priv; + + if (!bpf_map_hash) { + bpf_map_hash =3D hashmap__new(ptr_hash, ptr_equal, NULL); + if (!bpf_map_hash) + return -ENOMEM; + } + + old_priv =3D map_priv(map); + if (old_priv) { + bpf_map_priv__clear(map, old_priv); + return hashmap__set(bpf_map_hash, map, priv, NULL, NULL); + } + return hashmap__add(bpf_map_hash, map, priv); +} + static int bpf_map_op_setkey(struct bpf_map_op *op, struct parse_events_term *term) { @@ -1077,7 +1125,7 @@ static int bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op) { const char *map_name =3D bpf_map__name(map); - struct bpf_map_priv *priv =3D bpf_map__priv(map); + struct bpf_map_priv *priv =3D map_priv(map); =20 if (IS_ERR(priv)) { pr_debug("Failed to get private from map %s\n", map_name); @@ -1092,7 +1140,7 @@ bpf_map__add_op(struct bpf_map *map, struct bpf_map_o= p *op) } INIT_LIST_HEAD(&priv->ops_list); =20 - if (bpf_map__set_priv(map, priv, bpf_map_priv__clear)) { + if (map_set_priv(map, priv)) { free(priv); return -BPF_LOADER_ERRNO__INTERNAL; } @@ -1432,7 +1480,7 @@ bpf_map_config_foreach_key(struct bpf_map *map, struct bpf_map_op *op; const struct bpf_map_def *def; const char *name =3D bpf_map__name(map); - struct bpf_map_priv *priv =3D bpf_map__priv(map); + struct bpf_map_priv *priv =3D map_priv(map); =20 if (IS_ERR(priv)) { pr_debug("ERROR: failed to get private from map %s\n", name); @@ -1652,7 +1700,7 @@ struct evsel *bpf__setup_output_event(struct evlist *= evlist, const char *name) bool need_init =3D false; =20 bpf__perf_for_each_map_named(map, perf_obj, tmp, name) { - struct bpf_map_priv *priv =3D bpf_map__priv(map); + struct bpf_map_priv *priv =3D map_priv(map); =20 if (IS_ERR(priv)) return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL); @@ -1688,7 +1736,7 @@ struct evsel *bpf__setup_output_event(struct evlist *= evlist, const char *name) } =20 bpf__perf_for_each_map_named(map, perf_obj, tmp, name) { - struct bpf_map_priv *priv =3D bpf_map__priv(map); + struct bpf_map_priv *priv =3D map_priv(map); =20 if (IS_ERR(priv)) return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL); @@ -1700,7 +1748,7 @@ struct evsel *bpf__setup_output_event(struct evlist *= evlist, const char *name) if (!priv) return ERR_PTR(-ENOMEM); =20 - err =3D bpf_map__set_priv(map, priv, bpf_map_priv__clear); + err =3D map_set_priv(map, priv); if (err) { bpf_map_priv__clear(map, priv); return ERR_PTR(err); --=20 2.35.1 From nobody Sun Jun 28 00:08:49 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4A75C433F5 for ; Thu, 17 Feb 2022 13:19:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240875AbiBQNUJ (ORCPT ); Thu, 17 Feb 2022 08:20:09 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:42214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240864AbiBQNUH (ORCPT ); Thu, 17 Feb 2022 08:20:07 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2634E2AE734; Thu, 17 Feb 2022 05:19:53 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id A91D1B821AD; Thu, 17 Feb 2022 13:19:51 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1B81C340F3; Thu, 17 Feb 2022 13:19:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1645103990; bh=rR7j4YmApToV2YRSuDP85+mXkntJiYfEZ6H5iwYSzI0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fq+3M5303bdT8nnwZwd6StHMbYmnzty+zNmXGOyZhhOgWRNaORBj6kRFGKB6dmr6+ 6ozd59BmPk0ntm/0Np6Mmwuimuob2VS2m3st+CaS/M1GnGyJVTZsyDzYXQhyCJTy2v BP1B8WihX4nTQLj7aWRzuGdm70k1rQ/5te+3AlCoO5Yvq84a61SpnshVZIV7CkhVnJ YnbT7KMVJ8BinOYhglGJnTF3p0wgdcZfxuyMpRKO8V3qZCedsefEoDbLxMw+tOiAd5 9L8n2sDkevjRactDrAqq9On7WICoBvwjqZusCI+Ou+586bJN7d3S7kWzy6pC3SrzqM j8Oxuc8ZSEhAQ== From: Jiri Olsa To: Arnaldo Carvalho de Melo Cc: Andrii Nakryiko , lkml , Peter Zijlstra , Ingo Molnar , Mark Rutland , Namhyung Kim , Alexander Shishkin , Ian Rogers , linux-perf-users@vger.kernel.org, bpf@vger.kernel.org Subject: [PATCH 3/3] perf tools: Rework prologue generation code Date: Thu, 17 Feb 2022 14:19:16 +0100 Message-Id: <20220217131916.50615-4-jolsa@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220217131916.50615-1-jolsa@kernel.org> References: <20220217131916.50615-1-jolsa@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Some functions we use now for bpf prologue generation are going to be deprecated, so reworking the current code not to use them. We need to replace following functions/struct: bpf_program__set_prep bpf_program__nth_fd struct bpf_prog_prep_result Current code uses bpf_program__set_prep to hook perf callback before the program is loaded and provide new instructions with the prologue. We workaround this by using objects's 'unloaded' programs instructions for that specific program and load new ebpf programs with prologue using separate bpf_prog_load calls. We keep new ebpf program instances descriptors in bpf programs private struct. Suggested-by: Andrii Nakryiko Signed-off-by: Jiri Olsa --- tools/perf/util/bpf-loader.c | 122 +++++++++++++++++++++++++++++------ 1 file changed, 104 insertions(+), 18 deletions(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 6f87729817ad..03f917002c00 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -48,6 +48,7 @@ struct bpf_prog_priv { struct bpf_insn *insns_buf; int nr_types; int *type_mapping; + int *proglogue_fds; }; =20 struct bpf_perf_object { @@ -55,6 +56,11 @@ struct bpf_perf_object { struct bpf_object *obj; }; =20 +struct bpf_preproc_result { + struct bpf_insn *new_insn_ptr; + int new_insn_cnt; +}; + static LIST_HEAD(bpf_objects_list); static struct hashmap *bpf_program_hash; static struct hashmap *bpf_map_hash; @@ -176,14 +182,31 @@ struct bpf_object *bpf__prepare_load(const char *file= name, bool source) return obj; } =20 +static void close_prologue_programs(struct bpf_prog_priv *priv) +{ + struct perf_probe_event *pev; + int i, fd; + + if (!priv->need_prologue) + return; + pev =3D &priv->pev; + for (i =3D 0; i < pev->ntevs; i++) { + fd =3D close(priv->proglogue_fds[i]); + if (fd !=3D -1) + close(fd); + } +} + static void clear_prog_priv(const struct bpf_program *prog __maybe_unused, void *_priv) { struct bpf_prog_priv *priv =3D _priv; =20 + close_prologue_programs(priv); cleanup_perf_probe_events(&priv->pev, 1); zfree(&priv->insns_buf); + zfree(&priv->proglogue_fds); zfree(&priv->type_mapping); zfree(&priv->sys_name); zfree(&priv->evt_name); @@ -539,8 +562,8 @@ static int bpf__prepare_probe(void) =20 static int preproc_gen_prologue(struct bpf_program *prog, int n, - struct bpf_insn *orig_insns, int orig_insns_cnt, - struct bpf_prog_prep_result *res) + const struct bpf_insn *orig_insns, int orig_insns_cnt, + struct bpf_preproc_result *res) { struct bpf_prog_priv *priv =3D program_priv(prog); struct probe_trace_event *tev; @@ -588,7 +611,6 @@ preproc_gen_prologue(struct bpf_program *prog, int n, =20 res->new_insn_ptr =3D buf; res->new_insn_cnt =3D prologue_cnt + orig_insns_cnt; - res->pfd =3D NULL; return 0; =20 errout: @@ -696,7 +718,7 @@ static int hook_load_preprocessor(struct bpf_program *p= rog) struct bpf_prog_priv *priv =3D program_priv(prog); struct perf_probe_event *pev; bool need_prologue =3D false; - int err, i; + int i; =20 if (IS_ERR_OR_NULL(priv)) { pr_debug("Internal error when hook preprocessor\n"); @@ -727,6 +749,12 @@ static int hook_load_preprocessor(struct bpf_program *= prog) return 0; } =20 + /* + * Do not load programs that need prologue, because we need + * to add prologue first, check bpf_object__load_prologue. + */ + bpf_program__set_autoload(prog, false); + priv->need_prologue =3D true; priv->insns_buf =3D malloc(sizeof(struct bpf_insn) * BPF_MAXINSNS); if (!priv->insns_buf) { @@ -734,6 +762,13 @@ static int hook_load_preprocessor(struct bpf_program *= prog) return -ENOMEM; } =20 + priv->proglogue_fds =3D malloc(sizeof(int) * pev->ntevs); + if (!priv->proglogue_fds) { + pr_debug("Not enough memory: alloc prologue fds failed\n"); + return -ENOMEM; + } + memset(priv->proglogue_fds, -1, sizeof(int) * pev->ntevs); + priv->type_mapping =3D malloc(sizeof(int) * pev->ntevs); if (!priv->type_mapping) { pr_debug("Not enough memory: alloc type_mapping failed\n"); @@ -742,13 +777,7 @@ static int hook_load_preprocessor(struct bpf_program *= prog) memset(priv->type_mapping, -1, sizeof(int) * pev->ntevs); =20 - err =3D map_prologue(pev, priv->type_mapping, &priv->nr_types); - if (err) - return err; - - err =3D bpf_program__set_prep(prog, priv->nr_types, - preproc_gen_prologue); - return err; + return map_prologue(pev, priv->type_mapping, &priv->nr_types); } =20 int bpf__probe(struct bpf_object *obj) @@ -855,6 +884,66 @@ int bpf__unprobe(struct bpf_object *obj) return ret; } =20 +static int bpf_object__load_prologue(struct bpf_object *obj) +{ + const struct bpf_insn *orig_insns; + struct bpf_preproc_result res; + struct perf_probe_event *pev; + struct bpf_program *prog; + int orig_insns_cnt; + + bpf_object__for_each_program(prog, obj) { + struct bpf_prog_priv *priv =3D program_priv(prog); + int err, i, fd; + + if (IS_ERR_OR_NULL(priv)) { + pr_debug("bpf: failed to get private field\n"); + return -BPF_LOADER_ERRNO__INTERNAL; + } + + if (!priv->need_prologue) + continue; + + /* + * For each program that needs prologue we do following: + * + * - take its current instructions and use them + * to generate the new code with prologue + * + * - load new instructions with bpf_prog_load + * and keep the fd in proglogue_fds + * + * - new fd will be used bpf__foreach_event + * to connect this program with perf evsel + */ + orig_insns =3D bpf_program__insns(prog); + orig_insns_cnt =3D bpf_program__insn_cnt(prog); + + pev =3D &priv->pev; + for (i =3D 0; i < pev->ntevs; i++) { + err =3D preproc_gen_prologue(prog, i, orig_insns, + orig_insns_cnt, &res); + if (err) + return err; + + fd =3D bpf_prog_load(bpf_program__get_type(prog), + bpf_program__name(prog), "GPL", + res.new_insn_ptr, + res.new_insn_cnt, NULL); + if (fd < 0) { + char bf[128]; + + libbpf_strerror(-errno, bf, sizeof(bf)); + pr_debug("bpf: load objects with prologue failed: err=3D%d: (%s)\n", + -errno, bf); + return -errno; + } + priv->proglogue_fds[i] =3D fd; + } + } + return 0; +} + int bpf__load(struct bpf_object *obj) { int err; @@ -866,7 +955,7 @@ int bpf__load(struct bpf_object *obj) pr_debug("bpf: load objects failed: err=3D%d: (%s)\n", err, bf); return err; } - return 0; + return bpf_object__load_prologue(obj); } =20 int bpf__foreach_event(struct bpf_object *obj, @@ -901,13 +990,10 @@ int bpf__foreach_event(struct bpf_object *obj, for (i =3D 0; i < pev->ntevs; i++) { tev =3D &pev->tevs[i]; =20 - if (priv->need_prologue) { - int type =3D priv->type_mapping[i]; - - fd =3D bpf_program__nth_fd(prog, type); - } else { + if (priv->need_prologue) + fd =3D priv->proglogue_fds[i]; + else fd =3D bpf_program__fd(prog); - } =20 if (fd < 0) { pr_debug("bpf: failed to get file descriptor\n"); --=20 2.35.1