bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH dwarves v1] dwarf_loader: Fix skipped encoding of function BTF on 32-bit systems
@ 2025-04-10  8:33 Tony Ambardar
  2025-04-10 12:20 ` Alan Maguire
  0 siblings, 1 reply; 15+ messages in thread
From: Tony Ambardar @ 2025-04-10  8:33 UTC (permalink / raw)
  To: dwarves, bpf
  Cc: Tony Ambardar, Alan Maguire, Arnaldo Carvalho de Melo,
	Andrii Nakryiko, Alexei Starovoitov, Daniel Borkmann

While doing JIT development on armhf BTF kernels, I hit a strange issue
where some functions were missing in BTF data. This required considerable
debugging but can be reproduced simply:

$ bpftool --version
bpftool v7.6.0
using libbpf v1.6
features: llvm, skeletons

$ pahole --version
v1.29

$ pahole -J -j --btf_features=decl_tag,consistent_func,decl_tag_kfuncs .tmp_vmlinux_armhf
btf_encoder__tag_kfunc: failed to find kfunc 'scx_bpf_select_cpu_dfl' in BTF
btf_encoder__tag_kfuncs: failed to tag kfunc 'scx_bpf_select_cpu_dfl'

$ pfunct -Fbtf -E -f scx_bpf_select_cpu_dfl .tmp_vmlinux_armhf
<nothing>

$ pfunct -Fdwarf -E -f scx_bpf_select_cpu_dfl .tmp_vmlinux_armhf
s32 scx_bpf_select_cpu_dfl(struct task_struct * p, s32 prev_cpu, u64 wake_flags, bool * is_idle);

$ pahole -J -j --btf_features=decl_tag,decl_tag_kfuncs .tmp_vmlinux_armhf

$ pfunct -Fbtf -E -f scx_bpf_select_cpu_dfl .tmp_vmlinux_armhf
bpf_kfunc s32 scx_bpf_select_cpu_dfl(struct task_struct * p, s32 prev_cpu, u64 wake_flags, bool * is_idle);

The key things to note are the pahole 'consistent_func' feature and the u64
'wake_flags' parameter vs. arm 32-bit registers. These point to existing
code handling arguments larger than register-size, but only structs.

Generalize the code for any type of argument exceeding register size (i.e.
cu->addr_size). This should work for integral or aggregate types, and also
avoids a bug in the current code where a register-sized struct could be
mistaken for larger.

Fixes: a53c58158b76 ("dwarf_loader: Mark functions that do not use expected registers for params")
Signed-off-by: Tony Ambardar <tony.ambardar@gmail.com>
---
 dwarf_loader.c | 37 ++++++++++++-------------------------
 1 file changed, 12 insertions(+), 25 deletions(-)

diff --git a/dwarf_loader.c b/dwarf_loader.c
index e1ba7bc..22abfdb 100644
--- a/dwarf_loader.c
+++ b/dwarf_loader.c
@@ -2914,23 +2914,9 @@ out:
 	return 0;
 }
 
-static bool param__is_struct(struct cu *cu, struct tag *tag)
+static bool param__is_wide(struct cu *cu, struct tag *tag)
 {
-	struct tag *type = cu__type(cu, tag->type);
-
-	if (!type)
-		return false;
-
-	switch (type->tag) {
-	case DW_TAG_structure_type:
-		return true;
-	case DW_TAG_const_type:
-	case DW_TAG_typedef:
-		/* handle "typedef struct", const parameter */
-		return param__is_struct(cu, type);
-	default:
-		return false;
-	}
+	return tag__size(tag, cu) > cu->addr_size;
 }
 
 static int cu__resolve_func_ret_types_optimized(struct cu *cu)
@@ -2942,9 +2928,9 @@ static int cu__resolve_func_ret_types_optimized(struct cu *cu)
 		struct tag *tag = pt->entries[i];
 		struct parameter *pos;
 		struct function *fn = tag__function(tag);
-		bool has_unexpected_reg = false, has_struct_param = false;
+		bool has_unexpected_reg = false, has_wide_param = false;
 
-		/* mark function as optimized if parameter is, or
+		/* Mark function as optimized if parameter is, or
 		 * if parameter does not have a location; at this
 		 * point location presence has been marked in
 		 * abstract origins for cases where a parameter
@@ -2953,10 +2939,11 @@ static int cu__resolve_func_ret_types_optimized(struct cu *cu)
 		 *
 		 * Also mark functions which, due to optimization,
 		 * use an unexpected register for a parameter.
-		 * Exception is functions which have a struct
-		 * as a parameter, as multiple registers may
-		 * be used to represent it, throwing off register
-		 * to parameter mapping.
+		 * Exception is functions which have a wide
+		 * parameter, as multiple registers may be used
+		 * to represent it, throwing off register to
+		 * parameter mapping. Examples could include
+		 * structs or 64-bit types on a 32-bit arch.
 		 */
 		ftype__for_each_parameter(&fn->proto, pos) {
 			if (pos->optimized || !pos->has_loc)
@@ -2967,11 +2954,11 @@ static int cu__resolve_func_ret_types_optimized(struct cu *cu)
 		}
 		if (has_unexpected_reg) {
 			ftype__for_each_parameter(&fn->proto, pos) {
-				has_struct_param = param__is_struct(cu, &pos->tag);
-				if (has_struct_param)
+				has_wide_param = param__is_wide(cu, &pos->tag);
+				if (has_wide_param)
 					break;
 			}
-			if (!has_struct_param)
+			if (!has_wide_param)
 				fn->proto.unexpected_reg = 1;
 		}
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2025-06-30 17:33 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-10  8:33 [PATCH dwarves v1] dwarf_loader: Fix skipped encoding of function BTF on 32-bit systems Tony Ambardar
2025-04-10 12:20 ` Alan Maguire
2025-04-16 10:33   ` Tony Ambardar
2025-05-02  7:03     ` [PATCH dwarves v2] " Tony Ambardar
2025-05-08  9:38       ` Alexis Lothoré
2025-05-09  5:21         ` Tony Ambardar
2025-05-09  8:33           ` Alexis Lothoré
2025-05-12  8:41             ` Tony Ambardar
2025-05-08 13:24       ` Alan Maguire
2025-05-09  5:22         ` Tony Ambardar
2025-05-22  6:37       ` [PATCH dwarves v3] " Tony Ambardar
2025-06-24 16:14         ` Alan Maguire
2025-06-30 10:01           ` Alan Maguire
2025-06-30 13:51             ` Jiri Olsa
2025-06-30 17:32               ` Alan Maguire

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).