From nobody Sat Feb 7 20:57:56 2026 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1557334DCFE for ; Thu, 13 Nov 2025 12:40:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763037629; cv=none; b=taboEoFdiDcM3UXGTI+pvE16pv22WH50nPmG5325IjrjrMTmZgYKS4MAjFMBl4N7cKDa/5AiEqDza9XbzqXwrmZFZ/+IXC1C7A4iixihviW5b0lkRqlLTDk20Ev7Yg+oprrpfTrRWZwgxkXRtPKHKAiialN/NApNs2lG7d1VoEU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763037629; c=relaxed/simple; bh=/SlaGJTkL18pJIV6OQWhS1Oi+1EN1eU1ZBzlHYzFk3M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nL/ooQY9a9C+DQ8aDbxOjTMCreMjYYvz4bNZsEawsq9LOvPhTx161c2KQsbzUoLAOJ9D9ZSvOyDXkxRhQZCYIOthO2Fwq/qsuLrXz/jinZXXkJ/a6pUbMvkL0Qp49Z0LrZC3esItQrZ9qeCQ+jcD/xMhSxhPithJyv9YByw/s2M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TnkuDPjD; arc=none smtp.client-ip=209.85.221.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TnkuDPjD" Received: by mail-wr1-f43.google.com with SMTP id ffacd0b85a97d-42b312a08a2so636414f8f.1 for ; Thu, 13 Nov 2025 04:40:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1763037624; x=1763642424; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=O+HnPpm5RhuiKrpmA4CkyikXxRc8yfLzzeS2SA5/Vpc=; b=TnkuDPjD34mR8kKj63VTP4UPs4+fI/xWx9wFMk2V8oX9Rp+4g/EdBjcZuc6qWGjdBk AVXLJB9IlSy5xQ8Sqyuk5sFiBYEWxT2mapK1FMP9gx2Vbr81njmngr0Ji3fXVmLBdkA8 68TxkqMCYFFppaUgsAWA85hVSZ/uPdG4rHB4jGvKC9Zh/ZSKK+bKaHyLGqJi1dw4lUSc Ru92o+4hdf7FSjjcnUP9BqBD2EywP+B59I6QrW9IvzOZ22B5qI5FxHCC3NoPK+/44i4E +SRxqY/EneMh1zX5ZJ42ziLBcXOrBDqa5oLTYYiRtHIAPq2NDmUXzbsj6Q+hQqDi1JA0 WiHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763037624; x=1763642424; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=O+HnPpm5RhuiKrpmA4CkyikXxRc8yfLzzeS2SA5/Vpc=; b=SRL7FoQQLLk+W6plZfGhN1FCagzuYC+mkyp5DlVHApO1sFSnWC16JEHwB0bwpUa9aU SKt2x4RBUsX+YijfQxDrFwEK0WxCSNJsJ/U9dxX2etIpWBa0OwySyw7pS3bBZQdO1b6J QUYangnhhPcf53R5rtlBoXGnGth0Tt3LPJzVCnYRAtyCY1EHapfjxscwwWdB4D+eY+b8 5EVMLFJuJYehpaft0vFrHSRPP5KhsLoB2b4ht8sM5J+0nL7az3tzVt3rUICZWowoD8tA bZ0jh+DAjE4N6BkekQLm06xkZZ5AczyTY1ZmNrQVBa/XKkfYuvlJMliDw6CslfmEOjms +jiQ== X-Forwarded-Encrypted: i=1; AJvYcCVnHRfziEiqBidPVn6nTN35mAI6y81zI1GJfxcmdXRH7Ukvcuxj4tKMMvPczd3v1Tb/gLKeo+VplSGa/6s=@vger.kernel.org X-Gm-Message-State: AOJu0YxF/+Z0aRgrwbaRzzHf8Gs/dFrUYFmTHQDliU+/HdqUwzfpJdsS E0GjiW0TElPzFdBFD1FocMzc8FIfkNkNPeZWkOW6FyrTK7nySa4XOfo7 X-Gm-Gg: ASbGncvHfqzPoYBXMCvRY64LMFZSCxRRqIe8aRB7YC4BL7eSBEMlYFmf5IGZx16rnce vXleLFE4/ubznF3ukj+9YyK3YjAr0bM32B28ccwDiYtgQhOqcmGcYCiYuR0ASrEVR2o9Qcfmblm zKdlsriQ2/ct1mAZLlQmq21R7nyhWviLrh5XB1TwPTN18BtU/A9T8N80UMR7kuv9Rvqr/OyWOYP 3yw17+jxSntIpPGEEmRwWHIyvRRphlc5EWysnds5ZhEteKBpBwgHav3qBBoCd6Wa4BMwh9aNqFf y/HSQiZ5k3kE5HrGGRYl2SNFzyw2q+qrbwfkS/NiFPSWv1gh/Md5FlJJb6gMSFJO4C551Etvd5/ KjcJIvC0+Sf1CCN7ffYKrFEBzZYwO4U8yRY96jAeH/5006Z5bhjN4kpg8VlQVkYyteDvb6YWy/y 5KK7iodoc1zWi/ X-Google-Smtp-Source: AGHT+IGrghwk8ZTMecTIAkc+zfJCwdZGd4y4/jP7qk9XhljNu1+PNtNUQJ+bAW1fcaUSV6nQ8GYJ+g== X-Received: by 2002:a05:6000:4008:b0:429:d6dc:ae1a with SMTP id ffacd0b85a97d-42b4bd9bca6mr7014159f8f.30.1763037624173; Thu, 13 Nov 2025 04:40:24 -0800 (PST) Received: from paul-Precision-5770 ([80.12.41.69]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42b53f0b62dsm3697140f8f.24.2025.11.13.04.40.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 04:40:23 -0800 (PST) From: Paul Houssel X-Google-Original-From: Paul Houssel To: Paul Houssel , Eduard Zingerman , bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Martin Horth , Ouail Derghal , Guilhem Jazeron , Ludovic Paillat , Robin Theveniaut , Tristan d'Audibert , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan , Paul Houssel Subject: [PATCH v4 1/2] libbpf: fix BTF dedup to support recursive typedef definitions Date: Thu, 13 Nov 2025 13:39:50 +0100 Message-ID: X-Mailer: git-send-email 2.51.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Handle recursive typedefs in BTF deduplication Pahole fails to encode BTF for some Go projects (e.g. Kubernetes and Podman) due to recursive type definitions that create reference loops not representable in C. These recursive typedefs trigger a failure in the BTF deduplication algorithm. This patch extends btf_dedup_ref_type() to properly handle potential recursion for BTF_KIND_TYPEDEF, similar to how recursion is already handled for BTF_KIND_STRUCT. This allows pahole to successfully generate BTF for Go binaries using recursive types without impacting existing C-based workflows. Co-developed-by: Martin Horth Signed-off-by: Martin Horth Co-developed-by: Ouail Derghal Signed-off-by: Ouail Derghal Co-developed-by: Guilhem Jazeron Signed-off-by: Guilhem Jazeron Co-developed-by: Ludovic Paillat Signed-off-by: Ludovic Paillat Co-developed-by: Robin Theveniaut Signed-off-by: Robin Theveniaut Suggested-by: Tristan d'Audibert Signed-off-by: Paul Houssel Acked-by: Eduard Zingerman --- The issue was originally observed when attempting to encode BTF for Kubernetes binaries (kubectl, kubeadm): $ git clone --depth 1 https://github.com/kubernetes/kubernetes $ cd ./kubernetes $ make kubeadm DBG=3D1 $ pahole --btf_encode_detached=3Dkubeadm.btf _output/bin/kubeadm btf_encoder__encode: btf__dedup failed! Failed to encode BTF The root cause lies in recursive type definitions that cannot exist in C but are valid in Go. program.go: "package main type Foo func() Foo func main() { bar() } func bar() Foo { return nil }" Building and encoding this program with pahole triggers the same deduplication failure: $ go build -gcflags "all=3D-N -l" ./program.go $ pahole --btf_encode_detached=3Dprogram.btf program btf_encoder__encode: btf__dedup failed! Failed to encode BTF As noted in the comment of btf_dedup_ref_type(), the deduplication logic previously assumed recursion only occurs through structs or unions: "[...] there is no danger of encountering cycles because in C type system the only way to form type cycle is through struct/union, so any chain of reference types, even those taking part in a type cycle, will inevitably reach struct/union at some point." However, Go allows such recursion through typedef-like constructs (function types, aliases), requiring a special case for BTF_KIND_TYPEDEF. This patch introduces that special handling, ensuring pahole can handle Go-generated BTFs while maintaining compatibility with existing C workflows. --- tools/lib/bpf/btf.c | 71 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 9f141395c074..84a4b0abc8be 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -3901,6 +3901,20 @@ static int btf_dedup_strings(struct btf_dedup *d) return err; } =20 +/* + * Calculate type signature hash of TYPEDEF, ignoring referenced type IDs, + * as referenced type IDs equivalence is established separately during type + * graph equivalence check algorithm. + */ +static long btf_hash_typedef(struct btf_type *t) +{ + long h; + + h =3D hash_combine(0, t->name_off); + h =3D hash_combine(h, t->info); + return h; +} + static long btf_hash_common(struct btf_type *t) { long h; @@ -3918,6 +3932,13 @@ static bool btf_equal_common(struct btf_type *t1, st= ruct btf_type *t2) t1->size =3D=3D t2->size; } =20 +/* Check structural compatibility of two TYPEDEF. */ +static bool btf_equal_typedef(struct btf_type *t1, struct btf_type *t2) +{ + return t1->name_off =3D=3D t2->name_off && + t1->info =3D=3D t2->info; +} + /* Calculate type signature hash of INT or TAG. */ static long btf_hash_int_decl_tag(struct btf_type *t) { @@ -4844,13 +4865,30 @@ static void btf_dedup_merge_hypot_map(struct btf_de= dup *d) } } =20 +static inline long btf_hash_by_kind(struct btf_type *t, __u16 kind) +{ + if (kind =3D=3D BTF_KIND_TYPEDEF) + return btf_hash_typedef(t); + else + return btf_hash_struct(t); +} + +static inline bool btf_equal_by_kind(struct btf_type *t1, struct btf_type = *t2, __u16 kind) +{ + if (kind =3D=3D BTF_KIND_TYPEDEF) + return btf_equal_typedef(t1, t2); + else + return btf_shallow_equal_struct(t1, t2); +} + /* - * Deduplicate struct/union types. + * Deduplicate struct/union and typedef types. * * For each struct/union type its type signature hash is calculated, taking * into account type's name, size, number, order and names of fields, but * ignoring type ID's referenced from fields, because they might not be de= duped - * completely until after reference types deduplication phase. This type h= ash + * completely until after reference types deduplication phase. For each ty= pedef + * type, the hash is computed based on the type=E2=80=99s name and size. T= his type hash * is used to iterate over all potential canonical types, sharing same has= h. * For each canonical candidate we check whether type graphs that they form * (through referenced types in fields and so on) are equivalent using alg= orithm @@ -4882,18 +4920,20 @@ static int btf_dedup_struct_type(struct btf_dedup *= d, __u32 type_id) t =3D btf_type_by_id(d->btf, type_id); kind =3D btf_kind(t); =20 - if (kind !=3D BTF_KIND_STRUCT && kind !=3D BTF_KIND_UNION) + if (kind !=3D BTF_KIND_STRUCT && + kind !=3D BTF_KIND_UNION && + kind !=3D BTF_KIND_TYPEDEF) return 0; =20 - h =3D btf_hash_struct(t); + h =3D btf_hash_by_kind(t, kind); for_each_dedup_cand(d, hash_entry, h) { __u32 cand_id =3D hash_entry->value; int eq; =20 /* * Even though btf_dedup_is_equiv() checks for - * btf_shallow_equal_struct() internally when checking two - * structs (unions) for equivalence, we need to guard here + * btf_equal_by_kind() internally when checking two + * structs (unions) or typedefs for equivalence, we need to guard here * from picking matching FWD type as a dedup candidate. * This can happen due to hash collision. In such case just * relying on btf_dedup_is_equiv() would lead to potentially @@ -4901,7 +4941,7 @@ static int btf_dedup_struct_type(struct btf_dedup *d,= __u32 type_id) * FWD and compatible STRUCT/UNION are considered equivalent. */ cand_type =3D btf_type_by_id(d->btf, cand_id); - if (!btf_shallow_equal_struct(t, cand_type)) + if (!btf_equal_by_kind(t, cand_type, kind)) continue; =20 btf_dedup_clear_hypot_map(d); @@ -4939,18 +4979,18 @@ static int btf_dedup_struct_types(struct btf_dedup = *d) /* * Deduplicate reference type. * - * Once all primitive and struct/union types got deduplicated, we can easi= ly + * Once all primitive, struct/union and typedef types got deduplicated, we= can easily * deduplicate all other (reference) BTF types. This is done in two steps: * * 1. Resolve all referenced type IDs into their canonical type IDs. This - * resolution can be done either immediately for primitive or struct/union= types - * (because they were deduped in previous two phases) or recursively for + * resolution can be done either immediately for primitive, struct/union, = and typedef + * types (because they were deduped in previous two phases) or recursively= for * reference types. Recursion will always terminate at either primitive or - * struct/union type, at which point we can "unwind" chain of reference ty= pes - * one by one. There is no danger of encountering cycles because in C type - * system the only way to form type cycle is through struct/union, so any = chain - * of reference types, even those taking part in a type cycle, will inevit= ably - * reach struct/union at some point. + * struct/union and typedef types, at which point we can "unwind" chain of= reference + * types one by one. There is no danger of encountering cycles in C, as th= e only way to + * form a type cycle is through struct or union types. Go can form such cy= cles through + * typedef. Thus, any chain of reference types, even those taking part in = a type cycle, + * will inevitably reach a struct/union or typedef type at some point. * * 2. Once all referenced type IDs are resolved into canonical ones, BTF t= ype * becomes "stable", in the sense that no further deduplication will cause @@ -4982,7 +5022,6 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __= u32 type_id) case BTF_KIND_VOLATILE: case BTF_KIND_RESTRICT: case BTF_KIND_PTR: - case BTF_KIND_TYPEDEF: case BTF_KIND_FUNC: case BTF_KIND_TYPE_TAG: ref_type_id =3D btf_dedup_ref_type(d, t->type); --=20 2.51.0 From nobody Sat Feb 7 20:57:56 2026 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D1F1034F261 for ; Thu, 13 Nov 2025 12:40:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763037630; cv=none; b=BpobdL+LNAiuhAtOWR5w1K60pIHkFsRL6CiuG0FXDaGXC2VIXEjzD9PhLAfSF1KqvcF801cqmNlxvTAaQ1+9wXq50VAtMWMYFxwuJ/j4V+0LQiYit42ncsoIOxoP2tfK7gclvnBRcSYDNO0Q6/Na4boom4acgxWLw4RLnEQ2yPc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763037630; c=relaxed/simple; bh=ZDIjKrxNRsNKjDHyHEBYoPmLkLVi1miMphnKseqdm2M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LRemEy9qbq8xXTilWwCv99Ojm9G7x/Dzi5IDYSu5kFtS3RftLqsXjmMWFCwO8mBsMuzGED41eymd3lAHdhOn9or+TwSSSsIMu0ErKUSIFkOLUPwvgCWYFf80licmiwLcliQIvDGkqdNRcliWI/JCdj4Bt4UmrXP8mWwzKCPu89k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=PM28zDVD; arc=none smtp.client-ip=209.85.221.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PM28zDVD" Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-42b3b0d76fcso543435f8f.3 for ; Thu, 13 Nov 2025 04:40:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1763037627; x=1763642427; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MO9XnnVHj/rspITKiAGHVAzlJx09tqhwIOhjHMpSEAU=; b=PM28zDVDce/GS0oF5Z085lkACZLsnDDdLwESuUTD4Pl3O2qB4z06jXIZd8aT0OVH5t 7pl06Je3UXw6k7hqGunUJvNBMKrLWjZThhX7Y/1wVDp2AbOKMr+SLFYd4y2jvfatkmVk bOJgo2p+S+LEwhNkclVUmAAk5LrCeYeqvL1GpQTVcBKsBiW3+af/KjsUZpKYhc1U7ARE DjQ8I/6lt8tXTJT0u9INEEEvl7wwbpQBefvfhD5i541ytYq6nLVPt7HW2ScbweCrLwBy R4PTlDTYWgJ1y7RalE5S6UkwsJ4GvrTkIvCDwtE3J9PBELEf7DmSc95Kr65d3iqFn2XM qlwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763037627; x=1763642427; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=MO9XnnVHj/rspITKiAGHVAzlJx09tqhwIOhjHMpSEAU=; b=dDaL5j3QfqFTWUUrruR5U9t3o7f3onRjTrL5Jip+U1Mg2Nl2G6LQZQdIAvkRz9fWza hEcLWfJoFZZFJ4IqdHNlabnO/rHW9szSaKJN4/uycrFAkppmmASWbyWw+Xw6PuGvYq8Z yeyRnYiky25aGo132m4fU52t4l78KWM2sFDW2ZOS/8SqdIWinBr3fgzXXZe6oT7zV3Ud DBDoe+os4IkaCeouJ7ont8ZLBufVn2PfsgKXWw+Ey1ocTqdRsa/+yy3nCzc9fMyOvnIp BlBhGpWnHkPdJ6YH/5slJ7rxvTvdikhdKUKXYkwoWFmkn2q0gtPwvVP34t79HN/weMw1 HL/w== X-Forwarded-Encrypted: i=1; AJvYcCURa4VOpzRU8kQdzsnxNVVyqD9Dz48avDxpsqNI85/OxlXd6lqUZZ/uYUDLJYY/va9qN6lc2mHKDz6L6h4=@vger.kernel.org X-Gm-Message-State: AOJu0YytUNYULg3a4Thy5Crx28TnF5dnOveNtcRZ0IMSz7jcVAlWSAyc 6JIpoAecBxs1E0GM+QJUtsTPKZJGaTB52c2h2LpC4JOCR9U7DDoL8Fho X-Gm-Gg: ASbGnctAhG85HVhLCCqT7329jkjNmehK309LjuPMoes29crK0HDFMw0ejeo4c4Tyq6N f85TnlL4kAli2XPcRvfjSiPiiIl08heScitVXnj2QrqKLqk7E6F+lfeBfhJ3X86BrEaGcOLn3ex lFAMdnjqgIXUy3Z/CqJJT79RiD6XGTMGfNux/doRnJ0ESbm+PMw/7AwJkCAFasP8k/IdHNQ2qnw TT1KtslOeUmYiuoYY+H1XzGxiHMoFXwKT2nnMWKT8sp/9MGZM0D8frlSEbOmd/LEibalTO5r7Co 8KbdLa49ECWaNlilJjlvxnZgxZJlbGPFQ9+GTXKThiQ3D8dVO0GqXzJrnAJxnnYwSj+nt1lzx2G Ik2poDoPbLNZH+tDNiGYrmCHuv9hP/dFgfJp0zNvwGFlAk5BJms/exOxUHk2JBuQsx6w4jq4PrZ yiUcUdAYOEss8oNURbgUz7ZGI= X-Google-Smtp-Source: AGHT+IFMEpMMezmvxEMs766MRgjBKcLvtdSkSskQxUa3/4U12S0a20TELgCjrLTK7nBypapkTU9dgQ== X-Received: by 2002:a05:6000:2f86:b0:42b:43b4:2870 with SMTP id ffacd0b85a97d-42b4bb91d32mr6647570f8f.26.1763037627088; Thu, 13 Nov 2025 04:40:27 -0800 (PST) Received: from paul-Precision-5770 ([80.12.41.69]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42b53f0b62dsm3697140f8f.24.2025.11.13.04.40.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Nov 2025 04:40:26 -0800 (PST) From: Paul Houssel X-Google-Original-From: Paul Houssel To: Paul Houssel , Eduard Zingerman , bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Martin Horth , Ouail Derghal , Guilhem Jazeron , Ludovic Paillat , Robin Theveniaut , Tristan d'Audibert , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan , Paul Houssel Subject: [PATCH v4 2/2] selftests/bpf: add BTF dedup tests for recursive typedef definitions Date: Thu, 13 Nov 2025 13:39:51 +0100 Message-ID: <9fac2f744089f6090257d4c881914b79f6cd6c6a.1763037045.git.paul.houssel@orange.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add several ./test_progs tests: 1. btf/dedup:recursive typedef ensures that deduplication no longer fails on recursive typedefs. 2. btf/dedup:typedef ensures that typedefs are deduplicated correctly just as they were before this patch. Signed-off-by: Paul Houssel Acked-by: Eduard Zingerman --- tools/testing/selftests/bpf/prog_tests/btf.c | 65 ++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/s= elftests/bpf/prog_tests/btf.c index 8a9ba4292109..054ecb6b1e9f 100644 --- a/tools/testing/selftests/bpf/prog_tests/btf.c +++ b/tools/testing/selftests/bpf/prog_tests/btf.c @@ -7495,6 +7495,71 @@ static struct btf_dedup_test dedup_tests[] =3D { BTF_STR_SEC("\0t\0m1\0m2\0tag1\0tag2\0tag3"), }, }, +{ + .descr =3D "dedup: recursive typedef", + /* + * This test simulates a recursive typedef, which in GO is defined as suc= h: + * + * type Foo func() Foo + * + * In BTF terms, this is represented as a TYPEDEF referencing + * a FUNC_PROTO that returns the same TYPEDEF. + */ + .input =3D { + .raw_types =3D { + /* + * [1] typedef Foo -> func() Foo + * [2] func_proto() -> Foo + * [3] typedef Foo -> func() Foo + * [4] func_proto() -> Foo + */ + BTF_TYPEDEF_ENC(NAME_NTH(1), 2), /* [1] */ + BTF_FUNC_PROTO_ENC(1, 0), /* [2] */ + BTF_TYPEDEF_ENC(NAME_NTH(1), 4), /* [3] */ + BTF_FUNC_PROTO_ENC(3, 0), /* [4] */ + BTF_END_RAW, + }, + BTF_STR_SEC("\0Foo"), + }, + .expect =3D { + .raw_types =3D { + BTF_TYPEDEF_ENC(NAME_NTH(1), 2), /* [1] */ + BTF_FUNC_PROTO_ENC(1, 0), /* [2] */ + BTF_END_RAW, + }, + BTF_STR_SEC("\0Foo"), + }, +}, +{ + .descr =3D "dedup: typedef", + /* + * // CU 1: + * typedef int foo; + * + * // CU 2: + * typedef int foo; + */ + .input =3D { + .raw_types =3D { + /* CU 1 */ + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ + BTF_TYPEDEF_ENC(NAME_NTH(1), 1), /* [2] */ + /* CU 2 */ + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [3] */ + BTF_TYPEDEF_ENC(NAME_NTH(1), 3), /* [4] */ + BTF_END_RAW, + }, + BTF_STR_SEC("\0foo"), + }, + .expect =3D { + .raw_types =3D { + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ + BTF_TYPEDEF_ENC(NAME_NTH(1), 1), /* [2] */ + BTF_END_RAW, + }, + BTF_STR_SEC("\0foo"), + }, +}, { .descr =3D "dedup: typedef tags", .input =3D { --=20 2.51.0