All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ihor Solodrai <ihor.solodrai@linux.dev>
To: Alexei Starovoitov <ast@kernel.org>,
	Andrii Nakryiko <andrii@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Eduard Zingerman <eddyz87@gmail.com>,
	Kumar Kartikeya Dwivedi <memxor@gmail.com>,
	Quentin Monnet <qmo@kernel.org>
Cc: bpf@vger.kernel.org, Alan Maguire <alan.maguire@oracle.com>,
	Cupertino Miranda <cupertino.miranda@oracle.com>,
	David Faust <david.faust@oracle.com>,
	Ian Rogers <irogers@google.com>,
	"Jose E . Marchesi" <jose.marchesi@oracle.com>,
	Vineet Gupta <vineet.gupta@linux.dev>,
	Yonghong Song <yonghong.song@linux.dev>
Subject: [PATCH bpf-next v2 1/8] libbpf: Look up BTF strings without making BTF modifiable
Date: Fri, 23 Oct 2026 15:26:45 -0700	[thread overview]
Message-ID: <20261023222652.3927736-2-ihor.solodrai@linux.dev> (raw)
In-Reply-To: <20261023222652.3927736-1-ihor.solodrai@linux.dev>

btf__find_str() needs a hash index of the string section, and gets one
by making BTF modifiable. That copies types and strings out of the raw
data, and fails with -EOPNOTSUPP on BTF with unknown extension bytes.

btf__add_str() and split btf__dedup() look up strings in the base BTF
first. So adding a string to split BTF, or deduping it, makes the base
modifiable as a side effect, and fails if the base comes from a newer
kernel with new header fields.

Build the string index without making BTF modifiable, and reuse it if
BTF becomes modifiable later. The index can now exist on read-only
BTF, so btf__free() frees it unconditionally.

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
 tools/lib/bpf/btf.c | 36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index d2ff6f5d6d5b..d8907281c0ef 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -153,9 +153,9 @@ struct btf {
 	 */
 	int start_str_off;
 
-	/* only one of strs_data or strs_set can be non-NULL, depending on
-	 * whether BTF is in a modifiable state (strs_set is used) or not
-	 * (strs_data points inside raw_data)
+	/* strs_data points inside raw_data until BTF becomes modifiable,
+	 * then strings live in strs_set. Before that, strs_set may exist
+	 * as a lookup index for btf__find_str().
 	 */
 	void *strs_data;
 	/* a set of unique strings */
@@ -1258,9 +1258,9 @@ void btf__free(struct btf *btf)
 		 * which will be unconditionally freed below.
 		 */
 		free(btf->types_data);
-		strset__free(btf->strs_set);
 		free(btf->layout);
 	}
+	strset__free(btf->strs_set);
 	btf_free_raw_data(btf);
 	free(btf->raw_data_swapped);
 	free(btf->type_offs);
@@ -2042,6 +2042,21 @@ static void btf_invalidate_raw_data(struct btf *btf)
 	btf->named_start_id = 0;
 }
 
+static int btf_ensure_strs_set(struct btf *btf)
+{
+	struct strset *set;
+
+	if (btf->strs_set)
+		return 0;
+
+	set = strset__new(BTF_MAX_STR_OFFSET, btf->strs_data, btf->hdr.str_len);
+	if (IS_ERR(set))
+		return PTR_ERR(set);
+
+	btf->strs_set = set;
+	return 0;
+}
+
 /* Ensure BTF is ready to be modified (by splitting into a three memory
  * regions for types, strings and layout. Also invalidate cached
  * raw_data, if any.
@@ -2049,7 +2064,6 @@ static void btf_invalidate_raw_data(struct btf *btf)
 static int btf_ensure_modifiable(struct btf *btf)
 {
 	void *types, *layout = NULL;
-	struct strset *set = NULL;
 	int err = -ENOMEM;
 
 	if (btf_is_modifiable(btf)) {
@@ -2077,18 +2091,14 @@ static int btf_ensure_modifiable(struct btf *btf)
 		       btf->hdr.layout_len);
 	}
 
-	/* build lookup index for all strings */
-	set = strset__new(BTF_MAX_STR_OFFSET, btf->strs_data, btf->hdr.str_len);
-	if (IS_ERR(set)) {
-		err = PTR_ERR(set);
+	err = btf_ensure_strs_set(btf);
+	if (err)
 		goto err_out;
-	}
 
 	/* only when everything was successful, update internal state */
 	btf->types_data = types;
 	btf->types_data_cap = btf->hdr.type_len;
 	btf->strs_data = NULL;
-	btf->strs_set = set;
 	if (layout)
 		btf->layout = layout;
 	/* if BTF was created from scratch, all strings are guaranteed to be
@@ -2107,7 +2117,6 @@ static int btf_ensure_modifiable(struct btf *btf)
 	return 0;
 
 err_out:
-	strset__free(set);
 	free(types);
 	free(layout);
 	return err;
@@ -2130,8 +2139,7 @@ int btf__find_str(struct btf *btf, const char *s)
 			return off;
 	}
 
-	/* BTF needs to be in a modifiable state to build string lookup index */
-	err = btf_ensure_modifiable(btf);
+	err = btf_ensure_strs_set(btf);
 	if (err)
 		return libbpf_err(err);
 
-- 
2.56.0


  reply	other threads:[~2026-10-23 22:27 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-23 22:26 [PATCH bpf-next v2 0/8] bpftool: Per-record CO-RE attributes in the C dump Ihor Solodrai
2026-10-23 22:26 ` Ihor Solodrai [this message]
2026-10-23 22:39   ` [PATCH bpf-next v2 1/8] libbpf: Look up BTF strings without making BTF modifiable sashiko-bot
2026-10-23 22:26 ` [PATCH bpf-next v2 2/8] selftests/bpf: Cover unknown BTF header-extension bytes in btf dump Ihor Solodrai
2026-10-23 22:26 ` [PATCH bpf-next v2 3/8] bpftool: Apply __bpf_relocatable per record on BTF dump Ihor Solodrai
2026-10-27 18:03   ` Andrii Nakryiko
2026-10-27 18:15     ` Ihor Solodrai
2026-10-27 18:21       ` Andrii Nakryiko
2026-10-27 18:26         ` Ihor Solodrai
2026-10-27 21:25           ` Ihor Solodrai
2026-10-23 22:26 ` [PATCH bpf-next v2 4/8] bpftool: Skip __bpf_relocatable on verifier-rewritten context types Ihor Solodrai
2026-10-27 18:06   ` Andrii Nakryiko
2026-10-27 18:10     ` Andrii Nakryiko
2026-10-27 18:17     ` Ihor Solodrai
2026-10-23 22:26 ` [PATCH bpf-next v2 5/8] bpftool: Emit __bpf_static_offset " Ihor Solodrai
2026-10-27 18:10   ` Andrii Nakryiko
2026-10-23 22:26 ` [PATCH bpf-next v2 6/8] selftests/bpf: Cover record attributes in bpftool BTF dumps Ihor Solodrai
2026-10-23 22:26 ` [PATCH bpf-next v2 7/8] selftests/bpf: Cover context and socket accesses through vmlinux.h Ihor Solodrai
2026-10-23 22:26 ` [PATCH bpf-next v2 8/8] bpftool: Document __bpf_relocatable and __bpf_static_offset Ihor Solodrai
2026-10-23 22:28 ` [PATCH bpf-next v2 0/8] bpftool: Per-record CO-RE attributes in the C dump Vineet Gupta

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261023222652.3927736-2-ihor.solodrai@linux.dev \
    --to=ihor.solodrai@linux.dev \
    --cc=alan.maguire@oracle.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=cupertino.miranda@oracle.com \
    --cc=daniel@iogearbox.net \
    --cc=david.faust@oracle.com \
    --cc=eddyz87@gmail.com \
    --cc=irogers@google.com \
    --cc=jose.marchesi@oracle.com \
    --cc=memxor@gmail.com \
    --cc=qmo@kernel.org \
    --cc=vineet.gupta@linux.dev \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.