From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-183.mta1.migadu.com (out-183.mta1.migadu.com [95.215.58.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E23E830FF08 for ; Wed, 24 Jun 2026 00:56:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.183 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782262576; cv=none; b=OIdo0Cv6lMWaVlqCPVLn7s/UgzuFShRWoBIlAK1/dFZ1jLzBCDnHY2809kr3cgkY39pWB4viOHJmHuuKKknCHuc2kmnO7fgg4hzLTBZJa6DDVw2ebBdH8VIcFPlKGXAnPK8IbjXo7TXsiFV5VuBX5wD/Tzkl8E9eSxes42Twa94= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782262576; c=relaxed/simple; bh=S9dFaQNHVnY/Vdg33lk2uMsk0MNggJak83r/sxcJNP8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GufQQg8wVKSyLLy4g7x0cw1oWP4JPe9CgumZnGWPnVWeLVEjygo6yn+tIbQek2jkCy3MC1mkb9wS8wEn1/TV1zmr1xYOBgrkrkIBHG8Vg+RaF+N8ijsVqib60nYXIpRmTIiSVZz7J/VwNg1ypJmnQG1nXSFFI3XgHzYbOxU+vv4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=xnBeGwRc; arc=none smtp.client-ip=95.215.58.183 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="xnBeGwRc" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782262573; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=maIdhSgglPPfrpLL9a35d+Zuu2qcRVSxBs+tqS6jqcc=; b=xnBeGwRcWRxHNMcNbPHxUCK1Bv/nT/GhVazczoK/0FF64L+kubD2pJhaKlpfx6UB+YMUWf Wguy5N3XxbLyJhqratkrYuKcgrYrE0V49Z+ZXkMgkd5dcakO4zHPI2DOPnB4Zb+lKLLFV8 pyKilZNpDqaI3b81/hByooA+eOxF9OU= From: Ihor Solodrai To: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Eduard Zingerman , Kumar Kartikeya Dwivedi Cc: Alan Maguire , Jiri Olsa , Emil Tsalapatis , bpf@vger.kernel.org Subject: [PATCH bpf-next v2 4/4] selftests/bpf: Add kfunc set test to resolve_btfids Date: Tue, 23 Jun 2026 17:55:46 -0700 Message-ID: <20260624005546.1818483-5-ihor.solodrai@linux.dev> In-Reply-To: <20260624005546.1818483-1-ihor.solodrai@linux.dev> References: <20260624005546.1818483-1-ihor.solodrai@linux.dev> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT Extend the resolve_btfids selftest to cover kfunc sets defined with BTF_KFUNCS_START/BTF_KFUNCS_END. The test verifies that resolve_btfids correctly processes BTF_ID_FLAGS, resolves function IDs, and checks the kfunc set is sorted. Reviewed-by: Emil Tsalapatis Acked-by: Jiri Olsa Signed-off-by: Ihor Solodrai --- .../selftests/bpf/prog_tests/resolve_btfids.c | 79 +++++++++++++++++-- tools/testing/selftests/bpf/progs/btf_data.c | 10 +++ 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c b/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c index 98ce8fca2007..ac51fd454821 100644 --- a/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c +++ b/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c @@ -12,6 +12,10 @@ #define BTF_DATA_FILE "resolve_btfids.test.o.BTF" +#ifndef KF_FASTCALL +#define KF_FASTCALL (1 << 12) +#endif + struct symbol { const char *name; int type; @@ -28,6 +32,17 @@ struct symbol test_symbols[] = { { "func", BTF_KIND_FUNC, -1 }, }; +struct kfunc_symbol { + const char *name; + s32 id; + u32 flags; +}; + +static struct kfunc_symbol kfunc_symbols[] = { + { "kfunc_a", -1, 0 }, + { "kfunc_b", -1, KF_FASTCALL }, +}; + /* Align the .BTF_ids section to 4 bytes */ asm ( ".pushsection " BTF_IDS_SECTION " ,\"a\"; \n" @@ -35,9 +50,9 @@ asm ( ".popsection; \n"); /* - * test_list_local and test_set are .local symbols placed in .BTF_ids by - * inline asm, and are read here directly by C name. To the compiler they - * are plain, default-visibility extern objects. + * test_list_local, test_set and test_kfunc_set are .local symbols placed + * in .BTF_ids by inline asm, and are read here directly by C name. To the + * compiler they are plain, default-visibility extern objects. * * When test_progs is linked as a position-independent executable (PIE), * taking the address of such an extern is routed through the GOT. The @@ -69,6 +84,20 @@ BTF_ID(struct, S) BTF_ID(union, U) BTF_ID(func, func) BTF_SET_END(test_set) + +BTF_KFUNCS_START(test_kfunc_set) +BTF_ID_FLAGS(func, kfunc_a) +BTF_ID_FLAGS(func, kfunc_b, KF_FASTCALL) +BTF_KFUNCS_END(test_kfunc_set) + +/* + * Same kfuncs in reverse declaration order, so resolve_btfids has to + * actually sort at least one of the two sets. + */ +BTF_KFUNCS_START(test_kfunc_set_rev) +BTF_ID_FLAGS(func, kfunc_b, KF_FASTCALL) +BTF_ID_FLAGS(func, kfunc_a) +BTF_KFUNCS_END(test_kfunc_set_rev) #pragma GCC visibility pop extern __u32 test_list_global[]; @@ -92,6 +121,8 @@ __resolve_symbol(struct btf *btf, int type_id) if (!ASSERT_OK_PTR(type, "btf__type_by_id")) return -1; + str = btf__name_by_offset(btf, type->name_off); + for (i = 0; i < ARRAY_SIZE(test_symbols); i++) { if (test_symbols[i].id >= 0) continue; @@ -99,14 +130,20 @@ __resolve_symbol(struct btf *btf, int type_id) if (BTF_INFO_KIND(type->info) != test_symbols[i].type) continue; - str = btf__name_by_offset(btf, type->name_off); - if (!ASSERT_OK_PTR(str, "btf__name_by_offset")) - return -1; - if (!strcmp(str, test_symbols[i].name)) test_symbols[i].id = type_id; } + if (!btf_is_func(type)) + return 0; + + for (i = 0; i < ARRAY_SIZE(kfunc_symbols); i++) { + if (kfunc_symbols[i].id >= 0) + continue; + if (!strcmp(str, kfunc_symbols[i].name)) + kfunc_symbols[i].id = type_id; + } + return 0; } @@ -122,6 +159,31 @@ static int resolve_symbols(struct btf *btf) return 0; } +static void check_kfunc_set(struct btf_id_set8 *set) +{ + unsigned int i, j; + + ASSERT_EQ(set->flags, BTF_SET8_KFUNCS, "kfunc_set_flags"); + ASSERT_EQ(set->cnt, ARRAY_SIZE(kfunc_symbols), "kfunc_set_cnt"); + + for (i = 0; i < set->cnt; i++) { + for (j = 0; j < ARRAY_SIZE(kfunc_symbols); j++) { + if (kfunc_symbols[j].id == (s32)set->pairs[i].id) { + ASSERT_EQ(set->pairs[i].flags, + kfunc_symbols[j].flags, "kfunc_flags_check"); + break; + } + } + + ASSERT_TRUE(j < ARRAY_SIZE(kfunc_symbols), "kfunc_id_found"); + + if (i > 0) { + ASSERT_LE(set->pairs[i - 1].id, + set->pairs[i].id, "kfunc_sort_check"); + } + } +} + void test_resolve_btfids(void) { __u32 *test_list, *test_lists[] = { test_list_local, test_list_global }; @@ -162,6 +224,9 @@ void test_resolve_btfids(void) ASSERT_LE(test_set.ids[i - 1], test_set.ids[i], "sort_check"); } + check_kfunc_set(&test_kfunc_set); + check_kfunc_set(&test_kfunc_set_rev); + out: btf__free(btf); } diff --git a/tools/testing/selftests/bpf/progs/btf_data.c b/tools/testing/selftests/bpf/progs/btf_data.c index baa525275bde..8587658012c3 100644 --- a/tools/testing/selftests/bpf/progs/btf_data.c +++ b/tools/testing/selftests/bpf/progs/btf_data.c @@ -48,3 +48,13 @@ int func(struct root_struct *root) { return 0; } + +int kfunc_a(struct root_struct *root) +{ + return 0; +} + +int kfunc_b(struct root_struct *root) +{ + return 0; +} -- 2.54.0