From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Alan Maguire <alan.maguire@oracle.com>
Cc: Jiri Olsa <jolsa@kernel.org>,
Clark Williams <williams@redhat.com>,
Kate Carcia <kcarcia@redhat.com>,
dwarves@vger.kernel.org,
Arnaldo Carvalho de Melo <acme@redhat.com>,
Alexei Starovoitov <alexei.starovoitov@gmail.com>,
Andrii Nakryiko <andrii.nakryiko@gmail.com>,
"Jose E. Marchesi" <jose.marchesi@oracle.com>,
Namhyung Kim <namhyung@kernel.org>,
Nick Alcock <nick.alcock@oracle.com>,
Yonghong Song <yonghong.song@linux.dev>
Subject: [PATCH 2/4] libbpf: Check if there is extra data at the end of a BTF
Date: Thu, 7 Aug 2025 15:25:36 -0300 [thread overview]
Message-ID: <20250807182538.136498-3-acme@kernel.org> (raw)
In-Reply-To: <20250807182538.136498-1-acme@kernel.org>
From: Arnaldo Carvalho de Melo <acme@redhat.com>
We get the size for btf->raw_size from the ELF section where it is or
from the size of a detached BTF, check if there is extra data at the
end and avoid wasting space, when not using mmap.
This can happen if we generate BTF for all .o files and it then gets
combined by the linker, which is the default action when finding
unhandled sections with the same name in multiple .o files.
For instance:
root@x1:~/bla# bpftool -d btf dump file ~acme/btf2btf/vmlinux | wc -l
libbpf: BTF raw_size chopped from 380507209 to 238545
12084
root@x1:~/bla#
The above is one such file, where that vmlinux .BTF section has lots of
.BTF files combined by the linker.
A deduplicated one, generated by pahole + libbpf when converting from
DWARF has way more stuff in it and the raw_size matches the ELF size:
root@x1:~/bla# bpftool -d btf dump file /sys/kernel/btf/vmlinux |wc -l
355927
root@x1:~/bla#
Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: "Jose E. Marchesi" <jose.marchesi@oracle.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nick Alcock <nick.alcock@oracle.com>
Cc: Yonghong Song <yonghong.song@linux.dev>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/lib/bpf/btf.c | 42 ++++++++++++++++++++++++++++++++----------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 9bacd4dddff366bf..ee45d461d53bea9a 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -124,6 +124,9 @@ struct btf {
/* whether raw_data is a (read-only) mmap */
bool raw_data_is_mmap;
+ /* Wheter there was more data after the end of strings */
+ bool extra_raw_data;
+
/* BTF object FD, if loaded into kernel */
int fd;
@@ -225,10 +228,9 @@ static void btf_bswap_hdr(struct btf_header *h)
h->str_len = bswap_32(h->str_len);
}
-static int btf_parse_hdr(struct btf *btf)
+static int btf_parse_hdr(struct btf *btf, struct btf_header *hdr)
{
- struct btf_header *hdr = btf->hdr;
- __u32 meta_left;
+ __u32 meta_left, raw_size;
if (btf->raw_size < sizeof(struct btf_header)) {
pr_debug("BTF header not found\n");
@@ -271,6 +273,18 @@ static int btf_parse_hdr(struct btf *btf)
return -EINVAL;
}
+ /* If there is more data after the strings, it will not be used,
+ * so we might as well trim here and don't waste memory.
+ * This paves the way for a BTF archive, created by default
+ * by the linker when finding .BTF in multiple .o files.
+ */
+ raw_size = sizeof(*hdr) + hdr->str_off + hdr->str_len;
+ if (raw_size != btf->raw_size) {
+ pr_debug("BTF raw_size chopped from %u to %u\n", btf->raw_size, raw_size);
+ btf->raw_size = raw_size;
+ btf->extra_raw_data = true;
+ }
+
return 0;
}
@@ -1047,6 +1061,7 @@ struct btf *btf__new_empty_split(struct btf *base_btf)
static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf, bool is_mmap)
{
+ struct btf_header hdr;
struct btf *btf;
int err;
@@ -1065,24 +1080,31 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf, b
btf->start_str_off = base_btf->hdr->str_len;
}
+ /* We still don't know if this is an archive, i.e. if 'size' is
+ * the raw_size of a BTF or the sum of all BTFs in an archive,
+ * it'll be adjusted when we parse the header.
+ */
+ btf->raw_size = size;
+ memcpy(&hdr, data, sizeof(hdr));
+
+ err = btf_parse_hdr(btf, &hdr);
+ if (err)
+ goto done;
+
if (is_mmap) {
btf->raw_data = (void *)data;
btf->raw_data_is_mmap = true;
} else {
- btf->raw_data = malloc(size);
+ btf->raw_data = malloc(btf->raw_size);
if (!btf->raw_data) {
err = -ENOMEM;
goto done;
}
- memcpy(btf->raw_data, data, size);
+ memcpy(btf->raw_data, data, btf->raw_size);
}
- btf->raw_size = size;
-
btf->hdr = btf->raw_data;
- err = btf_parse_hdr(btf);
- if (err)
- goto done;
+ memcpy(btf->hdr, &hdr, sizeof(hdr));
btf->strs_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->str_off;
btf->types_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->type_off;
--
2.50.1
next prev parent reply other threads:[~2025-08-07 18:25 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-07 18:25 [RFC 0/4] BTF archive with unmodified pahole+toolchain Arnaldo Carvalho de Melo
2025-08-07 18:25 ` [PATCH 1/4] libbpf: Simplify error handling removing needless repeated err checks Arnaldo Carvalho de Melo
2025-08-07 18:25 ` Arnaldo Carvalho de Melo [this message]
2025-08-07 18:25 ` [PATCH 3/4] libbpf: Add support for detecting and dedup'ing a BTF archive Arnaldo Carvalho de Melo
2025-08-07 18:25 ` [PATCH 4/4] libbpf: Check if an ELF .BTF section is an archive and combine/dedup Arnaldo Carvalho de Melo
2025-08-07 18:46 ` [RFC 0/4] BTF archive with unmodified pahole+toolchain Arnaldo Carvalho de Melo
2025-08-07 20:23 ` Arnaldo Carvalho de Melo
2025-08-08 2:09 ` Alexei Starovoitov
[not found] ` <CA+JHD92DODDESCfwiiCs_ZQ5bGesK5NC+xe5EvONF5g+-Bg+9Q@mail.gmail.com>
2025-08-08 2:52 ` Alexei Starovoitov
2025-08-08 3:25 ` Arnaldo Carvalho de Melo
2025-08-08 3:33 ` Sam James
2025-08-08 3:54 ` Arnaldo Carvalho de Melo
2025-08-08 14:45 ` Nick Alcock
2025-08-08 15:15 ` Nick Alcock
2025-08-08 18:28 ` Eduard Zingerman
2025-08-08 19:10 ` Arnaldo Carvalho de Melo
2025-08-08 20:15 ` Eduard Zingerman
2025-08-08 20:59 ` Arnaldo Carvalho de Melo
2025-08-21 21:35 ` Nick Alcock
2025-08-27 0:14 ` Alexei Starovoitov
2025-09-15 10:11 ` Nick Alcock
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=20250807182538.136498-3-acme@kernel.org \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=alan.maguire@oracle.com \
--cc=alexei.starovoitov@gmail.com \
--cc=andrii.nakryiko@gmail.com \
--cc=dwarves@vger.kernel.org \
--cc=jolsa@kernel.org \
--cc=jose.marchesi@oracle.com \
--cc=kcarcia@redhat.com \
--cc=namhyung@kernel.org \
--cc=nick.alcock@oracle.com \
--cc=williams@redhat.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox