From patchwork Wed Oct 23 04:39:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrii Nakryiko X-Patchwork-Id: 13846413 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 6B946136337 for ; Wed, 23 Oct 2024 04:39:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729658353; cv=none; b=J2vI3e6vk1iYgG6W5GzV0pTuu9eR7kQrxFMlmA3rp+tiDxhAIaa1/oschgzF4J54gQyyniNZlNgZhhMFx6fAU3z4gWHBIvVAjLLysxavCjiG//xNAaDbJKCdhefk234U8NX/tRgOhNMJ0GTNaMDj9V8lca26sN3pjk8eNb8az90= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729658353; c=relaxed/simple; bh=19W/WGcextcNMPD0JtnkpPdA0ejILwtafAZ79zI8QCU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SWV/FVi2Rl6er8vEaChphzZ9Jdi703qiYf6rCons1QZSTUAYiLNv9nDvsV5vhgWUEXyd6Ok7ST71DoQGvHfYCsixvvD+PyRqK9IfFyM1hjVSGuB9IlitWqrBIt5KzCmTk/x50fLD/69x0DFjCytSFT1rofd+W1bwojnlE52FI8w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iVHn/X16; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iVHn/X16" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1D04CC4CEC6; Wed, 23 Oct 2024 04:39:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729658353; bh=19W/WGcextcNMPD0JtnkpPdA0ejILwtafAZ79zI8QCU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iVHn/X16JuHyPmojkxEOQ1+d59dnUooGntN2/xglzadaSZ++QXBQvEay/MST0E07X L0vKhnY5sIIHPcgxk1D5/LFgOX4Oc9bNeP+TPdpb9g5Y1km0AkOC7I67F88Yx1YJbB qA6eBMaxFVS42ztIJsbG7zvrdr+8+NTZREu9VCiU26wNv+b7yk59rtotOzXyuibJEM G8FhtrorDOcswwLkuq9kMoTtzoUM6c19fefqh2nWnm7Cd24PflYWJlGC9CakBsVneU Ve0jcPKsdAeUi5nWAr2qrtmZVidPArtbAB+eyDmluF67xKSxpfkNFdLzvyKrkHkqrw Vw2tJXRIimGuA== From: Andrii Nakryiko To: bpf@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net, martin.lau@kernel.org Cc: andrii@kernel.org, kernel-team@meta.com Subject: [PATCH bpf-next 1/3] selftests/bpf: fix test_spin_lock_fail.c's global vars usage Date: Tue, 22 Oct 2024 21:39:06 -0700 Message-ID: <20241023043908.3834423-2-andrii@kernel.org> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20241023043908.3834423-1-andrii@kernel.org> References: <20241023043908.3834423-1-andrii@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Global variables of special types (like `struct bpf_spin_lock`) make underlying ARRAY maps non-mmapable. To make this work with libbpf's mmaping logic, application is expected to declare such special variables as static, so libbpf doesn't even attempt to mmap() such ARRAYs. test_spin_lock_fail.c didn't follow this rule, but given it relied on this test to trigger failures, this went unnoticed, as we never got to the step of mmap()'ing these ARRAY maps. It is fragile and relies on specific sequence of libbpf steps, which are an internal implementation details. Fix the test by marking lockA and lockB as static. Fixes: c48748aea4f8 ("selftests/bpf: Add failure test cases for spin lock pairing") Signed-off-by: Andrii Nakryiko --- tools/testing/selftests/bpf/progs/test_spin_lock_fail.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c b/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c index 43f40c4fe241..1c8b678e2e9a 100644 --- a/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c +++ b/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c @@ -28,8 +28,8 @@ struct { }, }; -SEC(".data.A") struct bpf_spin_lock lockA; -SEC(".data.B") struct bpf_spin_lock lockB; +static struct bpf_spin_lock lockA SEC(".data.A"); +static struct bpf_spin_lock lockB SEC(".data.B"); SEC("?tc") int lock_id_kptr_preserve(void *ctx) From patchwork Wed Oct 23 04:39:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrii Nakryiko X-Patchwork-Id: 13846414 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 ABE091E515 for ; Wed, 23 Oct 2024 04:39:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729658356; cv=none; b=SUdZ3HBYRBMGUE9E5QzdFpHAAnSjCnHRopytSb2y5tZTsXGlBWqnpBg9kPXRM7FgYcXXCXSpLRs0RQMQZcUa2W285TMGT5c933ej3ptDm1lo/B+FIa2sKAnY8Ml00/E15ZWz0v0k8u1oh4SnjkYGwg/7R6NCumQ3ZHe6qFRRd3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729658356; c=relaxed/simple; bh=VJYtQt85B/rEAN0xMs2iD9uLz/2mbjJcjs5nRSDuMYg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J29q/ux8OptUoH11M2Xll/5CindeLJwl6d9VpefUYlXNxnLLXRA+FOspONc0B35ipLJIThsOAzO8tWWvlu+N/Vkk5HT3T7R9NiPcr0sG9FGd/9AN8UKGsVoc9CLoGh9aR9jxEiLPbxG6j30fRm/CgITKLWR8ghVYKlaZtjsrEjE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LxWfKpWR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LxWfKpWR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 516DFC4CEC6; Wed, 23 Oct 2024 04:39:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729658356; bh=VJYtQt85B/rEAN0xMs2iD9uLz/2mbjJcjs5nRSDuMYg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LxWfKpWRHXjbfJRll8duYQ09CQ0PiVz4AlDVBSdhxV1aD65e6JZMaVI6UmTjhM+b7 uTFjszhvAlDvXLdncB7yG1dYyITAChle1J8k7nVyUFKvvL81GOhFuI/ULZ5gCSHjM2 4bZCAbghaH/V3+VZ4DUzY8h8JNrAH6Kv7FSfjjGXmWpr/EwvSLdaBrXBI/ZJFuC/gM ZjyhF3d++TVP6uVnNySw2npbnMDEar30ImKj148ggcwap1HyQ2OTRw6NREuBVyNRUb uSHBrOBScBFJ6ojIi0eD372ms32MyZi1UPOCa2GbyBR2oV/nScO+y8vBFZP2vNL2vx t+4wjcwz6L8mw== From: Andrii Nakryiko To: bpf@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net, martin.lau@kernel.org Cc: andrii@kernel.org, kernel-team@meta.com, Alastair Robertson , Jonathan Wiepert Subject: [PATCH bpf-next 2/3] libbpf: move global data mmap()'ing into bpf_object__load() Date: Tue, 22 Oct 2024 21:39:07 -0700 Message-ID: <20241023043908.3834423-3-andrii@kernel.org> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20241023043908.3834423-1-andrii@kernel.org> References: <20241023043908.3834423-1-andrii@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Since BPF skeleton inception libbpf has been doing mmap()'ing of global data ARRAY maps in bpf_object__load_skeleton() API, which is used by code generated .skel.h files (i.e., by BPF skeletons only). This is wrong because if BPF object is loaded through generic bpf_object__load() API, global data maps won't be re-mmap()'ed after load step, and memory pointers returned from bpf_map__initial_value() would be wrong and won't reflect the actual memory shared between BPF program and user space. bpf_map__initial_value() return result is rarely used after load, so this went unnoticed for a really long time, until bpftrace project attempted to load BPF object through generic bpf_object__load() API and then used BPF subskeleton instantiated from such bpf_object. It turned out that .data/.rodata/.bss data updates through such subskeleton was "blackholed", all because libbpf wouldn't re-mmap() those maps during bpf_object__load() phase. Long story short, this step should be done by libbpf regardless of BPF skeleton usage, right after BPF map is created in the kernel. This patch moves this functionality into bpf_object__populate_internal_map() to achieve this. And bpf_object__load_skeleton() is now simple and almost trivial, only propagating these mmap()'ed pointers into user-supplied skeleton structs. We also do trivial adjustments to error reporting inside bpf_object__populate_internal_map() for consistency with the rest of libbpf's map-handling code. Reported-by: Alastair Robertson Reported-by: Jonathan Wiepert Fixes: d66562fba1ce ("libbpf: Add BPF object skeleton support") Signed-off-by: Andrii Nakryiko --- tools/lib/bpf/libbpf.c | 83 ++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 7c40286c3948..711173acbcef 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -5122,6 +5122,7 @@ bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map) enum libbpf_map_type map_type = map->libbpf_type; char *cp, errmsg[STRERR_BUFSIZE]; int err, zero = 0; + size_t mmap_sz; if (obj->gen_loader) { bpf_gen__map_update_elem(obj->gen_loader, map - obj->maps, @@ -5135,8 +5136,8 @@ bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map) if (err) { err = -errno; cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg)); - pr_warn("Error setting initial map(%s) contents: %s\n", - map->name, cp); + pr_warn("map '%s': failed to set initial contents: %s\n", + bpf_map__name(map), cp); return err; } @@ -5146,11 +5147,43 @@ bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *map) if (err) { err = -errno; cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg)); - pr_warn("Error freezing map(%s) as read-only: %s\n", - map->name, cp); + pr_warn("map '%s': failed to freeze as read-only: %s\n", + bpf_map__name(map), cp); return err; } } + + /* Remap anonymous mmap()-ed "map initialization image" as + * a BPF map-backed mmap()-ed memory, but preserving the same + * memory address. This will cause kernel to change process' + * page table to point to a different piece of kernel memory, + * but from userspace point of view memory address (and its + * contents, being identical at this point) will stay the + * same. This mapping will be released by bpf_object__close() + * as per normal clean up procedure. + */ + mmap_sz = bpf_map_mmap_sz(map); + if (map->def.map_flags & BPF_F_MMAPABLE) { + void *mmaped; + int prot; + + if (map->def.map_flags & BPF_F_RDONLY_PROG) + prot = PROT_READ; + else + prot = PROT_READ | PROT_WRITE; + mmaped = mmap(map->mmaped, mmap_sz, prot, MAP_SHARED | MAP_FIXED, map->fd, 0); + if (mmaped == MAP_FAILED) { + err = -errno; + pr_warn("map '%s': failed to re-mmap() contents: %d\n", + bpf_map__name(map), err); + return err; + } + map->mmaped = mmaped; + } else if (map->mmaped) { + munmap(map->mmaped, mmap_sz); + map->mmaped = NULL; + } + return 0; } @@ -5467,8 +5500,7 @@ bpf_object__create_maps(struct bpf_object *obj) err = bpf_object__populate_internal_map(obj, map); if (err < 0) goto err_out; - } - if (map->def.type == BPF_MAP_TYPE_ARENA) { + } else if (map->def.type == BPF_MAP_TYPE_ARENA) { map->mmaped = mmap((void *)(long)map->map_extra, bpf_map_mmap_sz(map), PROT_READ | PROT_WRITE, map->map_extra ? MAP_SHARED | MAP_FIXED : MAP_SHARED, @@ -13916,46 +13948,11 @@ int bpf_object__load_skeleton(struct bpf_object_skeleton *s) for (i = 0; i < s->map_cnt; i++) { struct bpf_map_skeleton *map_skel = (void *)s->maps + i * s->map_skel_sz; struct bpf_map *map = *map_skel->map; - size_t mmap_sz = bpf_map_mmap_sz(map); - int prot, map_fd = map->fd; - void **mmaped = map_skel->mmaped; - - if (!mmaped) - continue; - - if (!(map->def.map_flags & BPF_F_MMAPABLE)) { - *mmaped = NULL; - continue; - } - if (map->def.type == BPF_MAP_TYPE_ARENA) { - *mmaped = map->mmaped; + if (!map_skel->mmaped) continue; - } - - if (map->def.map_flags & BPF_F_RDONLY_PROG) - prot = PROT_READ; - else - prot = PROT_READ | PROT_WRITE; - /* Remap anonymous mmap()-ed "map initialization image" as - * a BPF map-backed mmap()-ed memory, but preserving the same - * memory address. This will cause kernel to change process' - * page table to point to a different piece of kernel memory, - * but from userspace point of view memory address (and its - * contents, being identical at this point) will stay the - * same. This mapping will be released by bpf_object__close() - * as per normal clean up procedure, so we don't need to worry - * about it from skeleton's clean up perspective. - */ - *mmaped = mmap(map->mmaped, mmap_sz, prot, MAP_SHARED | MAP_FIXED, map_fd, 0); - if (*mmaped == MAP_FAILED) { - err = -errno; - *mmaped = NULL; - pr_warn("failed to re-mmap() map '%s': %d\n", - bpf_map__name(map), err); - return libbpf_err(err); - } + *map_skel->mmaped = map->mmaped; } return 0; From patchwork Wed Oct 23 04:39:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrii Nakryiko X-Patchwork-Id: 13846415 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 41E378249F for ; Wed, 23 Oct 2024 04:39:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729658360; cv=none; b=Ctg3EtQJ8TNr7pBPy/65c5eSit318vIsKwoXYdtgct8v4eVR2JeNKC44Xr3WOP+Wd6hoinMZfsFu6K9niqkKL0Tgwn4bVOD9+LVCQ3PwlJkTmWQugsJOViHgCLEklgqPKBq55OW+POTHUvlLb6ETYiXHDxqvf4v3gL7/b/L47dE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729658360; c=relaxed/simple; bh=R4koJzpIjYR86FSm3H9Em2fkW2MiW86BajO5KxHB+8Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ewDyELLYPGkKVSiVoD0EMsymLIqiGLeJj86dygJ6r9lpZzI+6a7x4Jm34eOGiRT2rMSvF5lIUgG+YjvdRn0ttxwKK5AzwQHflfjzbjbuJ8PohEj2LAG7Un0wfZ4GCrrcOHYVTBmvdoj90Q9GfIL6QdOjfTekGArQrCnWlyZ93Iw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MzPQUCRh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MzPQUCRh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8EF11C4CEC6; Wed, 23 Oct 2024 04:39:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729658359; bh=R4koJzpIjYR86FSm3H9Em2fkW2MiW86BajO5KxHB+8Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MzPQUCRhK3PySkrIrQbecac2Ix8mSHPtpvhxkBxVTZ3RFMcZeJNLmBqupBNLEO55e lIWqoC9YpsGjlKZUGgRiyZedaozxW0AlKGCq/Xe6MbJn/aaZqoMQtUVSNwAbj7/S45 5sriQyv3DhILfuP8AfFVpKw0W0M+YNC30X2h9/t5WW8NDX5LF+KcyfUc+aE8xVkgl9 yt9AEERuFF32nBCi3mtNR3bgAoextHSCkpw/IRZ0/qadpc5xjAQZnfuBHcx027w1/q ETqs+u0VyamhZ6f71EnMbZ78//aLyb0zEtr+O7pxArE8W+Zkf8OXwrf5Q8fjKMsLWO Xbfm9yM6dStbQ== From: Andrii Nakryiko To: bpf@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net, martin.lau@kernel.org Cc: andrii@kernel.org, kernel-team@meta.com Subject: [PATCH bpf-next 3/3] selftests/bpf: validate generic bpf_object and subskel APIs work together Date: Tue, 22 Oct 2024 21:39:08 -0700 Message-ID: <20241023043908.3834423-4-andrii@kernel.org> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20241023043908.3834423-1-andrii@kernel.org> References: <20241023043908.3834423-1-andrii@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Add a new subtest validating that bpf_object loaded and initialized through generic APIs is still interoperable with BPF subskeleton, including initialization and reading of global variables. Signed-off-by: Andrii Nakryiko --- .../selftests/bpf/prog_tests/subskeleton.c | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/prog_tests/subskeleton.c b/tools/testing/selftests/bpf/prog_tests/subskeleton.c index 9c31b7004f9c..fdf13ed0152a 100644 --- a/tools/testing/selftests/bpf/prog_tests/subskeleton.c +++ b/tools/testing/selftests/bpf/prog_tests/subskeleton.c @@ -46,7 +46,8 @@ static int subskeleton_lib_subresult(struct bpf_object *obj) return result; } -void test_subskeleton(void) +/* initialize and load through skeleton, then instantiate subskeleton out of it */ +static void subtest_skel_subskeleton(void) { int err, result; struct test_subskeleton *skel; @@ -76,3 +77,76 @@ void test_subskeleton(void) cleanup: test_subskeleton__destroy(skel); } + +/* initialize and load through generic bpf_object API, then instantiate subskeleton out of it */ +static void subtest_obj_subskeleton(void) +{ + int err, result; + const void *elf_bytes; + size_t elf_bytes_sz = 0, rodata_sz = 0, bss_sz = 0; + struct bpf_object *obj; + const struct bpf_map *map; + const struct bpf_program *prog; + struct bpf_link *link = NULL; + struct test_subskeleton__rodata *rodata; + struct test_subskeleton__bss *bss; + + elf_bytes = test_subskeleton__elf_bytes(&elf_bytes_sz); + if (!ASSERT_OK_PTR(elf_bytes, "elf_bytes")) + return; + + obj = bpf_object__open_mem(elf_bytes, elf_bytes_sz, NULL); + if (!ASSERT_OK_PTR(obj, "obj_open_mem")) + return; + + map = bpf_object__find_map_by_name(obj, ".rodata"); + if (!ASSERT_OK_PTR(map, "rodata_map_by_name")) + goto cleanup; + + rodata = bpf_map__initial_value(map, &rodata_sz); + if (!ASSERT_OK_PTR(rodata, "rodata_get")) + goto cleanup; + + rodata->rovar1 = 10; + rodata->var1 = 1; + subskeleton_lib_setup(obj); + + err = bpf_object__load(obj); + if (!ASSERT_OK(err, "obj_load")) + goto cleanup; + + prog = bpf_object__find_program_by_name(obj, "handler1"); + if (!ASSERT_OK_PTR(prog, "prog_by_name")) + goto cleanup; + + link = bpf_program__attach(prog); + if (!ASSERT_OK_PTR(link, "prog_attach")) + goto cleanup; + + /* trigger tracepoint */ + usleep(1); + + map = bpf_object__find_map_by_name(obj, ".bss"); + if (!ASSERT_OK_PTR(map, "bss_map_by_name")) + goto cleanup; + + bss = bpf_map__initial_value(map, &bss_sz); + if (!ASSERT_OK_PTR(rodata, "rodata_get")) + goto cleanup; + + result = subskeleton_lib_subresult(obj) * 10; + ASSERT_EQ(bss->out1, result, "out1"); + +cleanup: + bpf_link__destroy(link); + bpf_object__close(obj); +} + + +void test_subskeleton(void) +{ + if (test__start_subtest("skel_subskel")) + subtest_skel_subskeleton(); + if (test__start_subtest("obj_subskel")) + subtest_obj_subskeleton(); +}