* [PATCH bpf-next v2] resolve_btfids: Implement --patch_btfids
@ 2025-12-31 1:25 Ihor Solodrai
2025-12-31 17:07 ` Alexei Starovoitov
2025-12-31 17:10 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: Ihor Solodrai @ 2025-12-31 1:25 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Nathan Chancellor,
Nicolas Schier
Cc: bpf, linux-kbuild
Recent changes in BTF generation [1] rely on ${OBJCOPY} command to
update .BTF_ids section data in target ELF files.
This exposed a bug in llvm-objcopy --update-section code path, that
may lead to corruption of a target ELF file. Specifically, because of
the bug st_shndx of some symbols may be (incorrectly) set to 0xffff
(SHN_XINDEX) [2][3].
While there is a pending fix for LLVM, it'll take some time before it
lands (likely in 22.x). And the kernel build must keep working with
older LLVM toolchains in the foreseeable future.
Using GNU objcopy for .BTF_ids update would work, but it would require
changes to LLVM-based build process, likely breaking existing build
environments as discussed in [2].
To work around llvm-objcopy bug, implement --patch_btfids code path in
resolve_btfids as a drop-in replacement for:
${OBJCOPY} --update-section .BTF_ids=${btf_ids} ${elf}
Which works specifically for .BTF_ids section:
${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${elf}
This feature in resolve_btfids can be removed at some point in the
future, when llvm-objcopy with a relevant bugfix becomes common.
[1] https://lore.kernel.org/bpf/20251219181321.1283664-1-ihor.solodrai@linux.dev/
[2] https://lore.kernel.org/bpf/20251224005752.201911-1-ihor.solodrai@linux.dev/
[3] https://github.com/llvm/llvm-project/issues/168060#issuecomment-3533552952
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
Successful BPF CI run: https://github.com/kernel-patches/bpf/actions/runs/20608321584
---
scripts/gen-btf.sh | 2 +-
scripts/link-vmlinux.sh | 2 +-
tools/bpf/resolve_btfids/main.c | 117 +++++++++++++++++++++++++++
tools/testing/selftests/bpf/Makefile | 2 +-
4 files changed, 120 insertions(+), 3 deletions(-)
diff --git a/scripts/gen-btf.sh b/scripts/gen-btf.sh
index 12244dbe097c..0aec86615416 100755
--- a/scripts/gen-btf.sh
+++ b/scripts/gen-btf.sh
@@ -123,7 +123,7 @@ embed_btf_data()
fi
local btf_ids="${ELF_FILE}.BTF_ids"
if [ -f "${btf_ids}" ]; then
- ${OBJCOPY} --update-section .BTF_ids=${btf_ids} ${ELF_FILE}
+ ${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${ELF_FILE}
fi
}
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index e2207e612ac3..1915adf3249b 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -266,7 +266,7 @@ vmlinux_link "${VMLINUX}"
if is_enabled CONFIG_DEBUG_INFO_BTF; then
info OBJCOPY ${btfids_vmlinux}
- ${OBJCOPY} --update-section .BTF_ids=${btfids_vmlinux} ${VMLINUX}
+ ${RESOLVE_BTFIDS} --patch_btfids ${btfids_vmlinux} ${VMLINUX}
fi
mksysmap "${VMLINUX}" System.map
diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
index 2cbc252259be..df39982f51df 100644
--- a/tools/bpf/resolve_btfids/main.c
+++ b/tools/bpf/resolve_btfids/main.c
@@ -862,8 +862,119 @@ static inline int make_out_path(char *buf, u32 buf_sz, const char *in_path, cons
return 0;
}
+/*
+ * Patch the .BTF_ids section of an ELF file with data from provided file.
+ * Equivalent to: objcopy --update-section .BTF_ids=<btfids> <elf>
+ *
+ * 1. Find .BTF_ids section in the ELF
+ * 2. Verify that blob file size matches section size
+ * 3. Update section data buffer with blob data
+ * 4. Write the ELF file
+ */
+static int patch_btfids(const char *btfids_path, const char *elf_path)
+{
+ Elf_Scn *scn = NULL;
+ FILE *btfids_file;
+ size_t shdrstrndx;
+ int fd, err = -1;
+ Elf_Data *data;
+ struct stat st;
+ GElf_Shdr sh;
+ char *name;
+ Elf *elf;
+
+ elf_version(EV_CURRENT);
+
+ fd = open(elf_path, O_RDWR, 0666);
+ if (fd < 0) {
+ pr_err("FAILED to open %s: %s\n", elf_path, strerror(errno));
+ return -1;
+ }
+
+ elf = elf_begin(fd, ELF_C_RDWR_MMAP, NULL);
+ if (!elf) {
+ close(fd);
+ pr_err("FAILED cannot create ELF descriptor: %s\n", elf_errmsg(-1));
+ return -1;
+ }
+
+ elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT);
+
+ if (elf_getshdrstrndx(elf, &shdrstrndx) != 0) {
+ pr_err("FAILED cannot get shdr str ndx\n");
+ goto out;
+ }
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+
+ if (gelf_getshdr(scn, &sh) != &sh) {
+ pr_err("FAILED to get section header\n");
+ goto out;
+ }
+
+ name = elf_strptr(elf, shdrstrndx, sh.sh_name);
+ if (!name)
+ continue;
+
+ if (strcmp(name, BTF_IDS_SECTION) == 0)
+ break;
+ }
+
+ if (!scn) {
+ pr_err("FAILED: section %s not found in %s\n", BTF_IDS_SECTION, elf_path);
+ goto out;
+ }
+
+ data = elf_getdata(scn, NULL);
+ if (!data) {
+ pr_err("FAILED to get %s section data from %s\n", BTF_IDS_SECTION, elf_path);
+ goto out;
+ }
+
+ if (stat(btfids_path, &st) < 0) {
+ pr_err("FAILED to stat %s: %s\n", btfids_path, strerror(errno));
+ goto out;
+ }
+
+ if ((size_t)st.st_size != data->d_size) {
+ pr_err("FAILED: size mismatch - %s section in %s is %zu bytes, %s is %zu bytes\n",
+ BTF_IDS_SECTION, elf_path, data->d_size, btfids_path, (size_t)st.st_size);
+ goto out;
+ }
+
+ btfids_file = fopen(btfids_path, "rb");
+ if (!btfids_file) {
+ pr_err("FAILED to open %s: %s\n", btfids_path, strerror(errno));
+ goto out;
+ }
+
+ pr_debug("Copying data from %s to %s section of %s (%zu bytes)\n",
+ btfids_path, BTF_IDS_SECTION, elf_path, data->d_size);
+
+ if (fread(data->d_buf, data->d_size, 1, btfids_file) != 1) {
+ pr_err("FAILED to read %s\n", btfids_path);
+ fclose(btfids_file);
+ goto out;
+ }
+ fclose(btfids_file);
+
+ elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
+ if (elf_update(elf, ELF_C_WRITE) < 0) {
+ pr_err("FAILED to update ELF file %s\n", elf_path);
+ goto out;
+ }
+
+ err = 0;
+out:
+ elf_end(elf);
+ close(fd);
+
+ return err;
+}
+
static const char * const resolve_btfids_usage[] = {
"resolve_btfids [<options>] <ELF object>",
+ "resolve_btfids --patch_btfids <.BTF_ids file> <ELF object>",
NULL
};
@@ -880,6 +991,7 @@ int main(int argc, const char **argv)
.funcs = RB_ROOT,
.sets = RB_ROOT,
};
+ const char *btfids_path = NULL;
bool fatal_warnings = false;
char out_path[PATH_MAX];
@@ -894,6 +1006,8 @@ int main(int argc, const char **argv)
"turn warnings into errors"),
OPT_BOOLEAN(0, "distill_base", &obj.distill_base,
"distill --btf_base and emit .BTF.base section data"),
+ OPT_STRING(0, "patch_btfids", &btfids_path, "file",
+ "path to .BTF_ids section data blob to patch into ELF file"),
OPT_END()
};
int err = -1;
@@ -905,6 +1019,9 @@ int main(int argc, const char **argv)
obj.path = argv[0];
+ if (btfids_path)
+ return patch_btfids(btfids_path, obj.path);
+
if (load_btf(&obj))
goto out;
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index f28a32b16ff0..9488d076c740 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -657,7 +657,7 @@ $(TRUNNER_TEST_OBJS): $(TRUNNER_OUTPUT)/%.test.o: \
$$(if $$(TEST_NEEDS_BTFIDS), \
$$(call msg,BTFIDS,$(TRUNNER_BINARY),$$@) \
$(RESOLVE_BTFIDS) --btf $(TRUNNER_OUTPUT)/btf_data.bpf.o $$@; \
- $(OBJCOPY) --update-section .BTF_ids=$$@.BTF_ids $$@)
+ $(RESOLVE_BTFIDS) --patch_btfids $$@.BTF_ids $$@)
$(TRUNNER_TEST_OBJS:.o=.d): $(TRUNNER_OUTPUT)/%.test.d: \
$(TRUNNER_TESTS_DIR)/%.c \
--
2.52.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf-next v2] resolve_btfids: Implement --patch_btfids
2025-12-31 1:25 [PATCH bpf-next v2] resolve_btfids: Implement --patch_btfids Ihor Solodrai
@ 2025-12-31 17:07 ` Alexei Starovoitov
2025-12-31 17:10 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Alexei Starovoitov @ 2025-12-31 17:07 UTC (permalink / raw)
To: Ihor Solodrai
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Nathan Chancellor,
Nicolas Schier, bpf, Linux Kbuild mailing list
On Tue, Dec 30, 2025 at 5:26 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> Recent changes in BTF generation [1] rely on ${OBJCOPY} command to
> update .BTF_ids section data in target ELF files.
>
> This exposed a bug in llvm-objcopy --update-section code path, that
> may lead to corruption of a target ELF file. Specifically, because of
> the bug st_shndx of some symbols may be (incorrectly) set to 0xffff
> (SHN_XINDEX) [2][3].
>
> While there is a pending fix for LLVM, it'll take some time before it
> lands (likely in 22.x). And the kernel build must keep working with
> older LLVM toolchains in the foreseeable future.
>
> Using GNU objcopy for .BTF_ids update would work, but it would require
> changes to LLVM-based build process, likely breaking existing build
> environments as discussed in [2].
>
> To work around llvm-objcopy bug, implement --patch_btfids code path in
> resolve_btfids as a drop-in replacement for:
>
> ${OBJCOPY} --update-section .BTF_ids=${btf_ids} ${elf}
>
> Which works specifically for .BTF_ids section:
>
> ${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${elf}
>
> This feature in resolve_btfids can be removed at some point in the
> future, when llvm-objcopy with a relevant bugfix becomes common.
>
> [1] https://lore.kernel.org/bpf/20251219181321.1283664-1-ihor.solodrai@linux.dev/
> [2] https://lore.kernel.org/bpf/20251224005752.201911-1-ihor.solodrai@linux.dev/
> [3] https://github.com/llvm/llvm-project/issues/168060#issuecomment-3533552952
>
> Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
>
> ---
>
> Successful BPF CI run: https://github.com/kernel-patches/bpf/actions/runs/20608321584
> ---
> scripts/gen-btf.sh | 2 +-
> scripts/link-vmlinux.sh | 2 +-
> tools/bpf/resolve_btfids/main.c | 117 +++++++++++++++++++++++++++
> tools/testing/selftests/bpf/Makefile | 2 +-
> 4 files changed, 120 insertions(+), 3 deletions(-)
>
> diff --git a/scripts/gen-btf.sh b/scripts/gen-btf.sh
> index 12244dbe097c..0aec86615416 100755
> --- a/scripts/gen-btf.sh
> +++ b/scripts/gen-btf.sh
> @@ -123,7 +123,7 @@ embed_btf_data()
> fi
> local btf_ids="${ELF_FILE}.BTF_ids"
> if [ -f "${btf_ids}" ]; then
> - ${OBJCOPY} --update-section .BTF_ids=${btf_ids} ${ELF_FILE}
> + ${RESOLVE_BTFIDS} --patch_btfids ${btf_ids} ${ELF_FILE}
> fi
> }
>
> diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
> index e2207e612ac3..1915adf3249b 100755
> --- a/scripts/link-vmlinux.sh
> +++ b/scripts/link-vmlinux.sh
> @@ -266,7 +266,7 @@ vmlinux_link "${VMLINUX}"
>
> if is_enabled CONFIG_DEBUG_INFO_BTF; then
> info OBJCOPY ${btfids_vmlinux}
> - ${OBJCOPY} --update-section .BTF_ids=${btfids_vmlinux} ${VMLINUX}
> + ${RESOLVE_BTFIDS} --patch_btfids ${btfids_vmlinux} ${VMLINUX}
> fi
Applied, but please follow up to reduce the verbosity
OBJCOPY net/mptcp/mptcp_diag.ko.BTF
OBJCOPY net/bridge/br_netfilter.ko.BTF
OBJCOPY net/bridge/netfilter/ebt_log.ko.BTF
OBJCOPY net/caif/caif.ko.BTF
OBJCOPY net/bridge/netfilter/ebt_ip.ko.BTF
BTFIDS net/netfilter/ipvs/ip_vs.ko
OBJCOPY net/netfilter/ipvs/ip_vs.ko.BTF
BTFIDS drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko
OBJCOPY drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko.BTF
All of these OBJCOPY lines are not correct anymore and can
be simply removed. No need to yell at the user about these steps.
imo BTFIDS lines can be removed too. They just scroll on the screen.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH bpf-next v2] resolve_btfids: Implement --patch_btfids
2025-12-31 1:25 [PATCH bpf-next v2] resolve_btfids: Implement --patch_btfids Ihor Solodrai
2025-12-31 17:07 ` Alexei Starovoitov
@ 2025-12-31 17:10 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-12-31 17:10 UTC (permalink / raw)
To: Ihor Solodrai
Cc: ast, daniel, andrii, martin.lau, eddyz87, nathan, nsc, bpf,
linux-kbuild
Hello:
This patch was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Tue, 30 Dec 2025 17:25:57 -0800 you wrote:
> Recent changes in BTF generation [1] rely on ${OBJCOPY} command to
> update .BTF_ids section data in target ELF files.
>
> This exposed a bug in llvm-objcopy --update-section code path, that
> may lead to corruption of a target ELF file. Specifically, because of
> the bug st_shndx of some symbols may be (incorrectly) set to 0xffff
> (SHN_XINDEX) [2][3].
>
> [...]
Here is the summary with links:
- [bpf-next,v2] resolve_btfids: Implement --patch_btfids
https://git.kernel.org/bpf/bpf-next/c/1a8fa7faf489
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-12-31 17:13 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-31 1:25 [PATCH bpf-next v2] resolve_btfids: Implement --patch_btfids Ihor Solodrai
2025-12-31 17:07 ` Alexei Starovoitov
2025-12-31 17:10 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox