From: Vineet Gupta <vineet.gupta@linux.dev>
To: dwarves@vger.kernel.org
Cc: bpf@vger.kernel.org, Andrii Nakryiko <andrii@kernel.org>,
acme@kernel.org, Alan Maguire <alan.maguire@oracle.com>,
Emil Tsalapatis <emil@etsalapatis.com>,
jose.marchesi@oracle.com, David Faust <david.faust@oracle.com>,
Yonghong Song <yonghong.song@linux.dev>,
Vineet Gupta <vineet.gupta@linux.dev>
Subject: [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test
Date: Wed, 17 Jun 2026 17:57:31 -0700 [thread overview]
Message-ID: <20260618005731.273181-6-vineet.gupta@linux.dev> (raw)
In-Reply-To: <20260618005731.273181-1-vineet.gupta@linux.dev>
From: Alan Maguire <alan.maguire@oracle.com>
Add a test that compiles a pointer carrying two btf_type_tags
(__tag(outer) __tag(inner)) and checks the BTF that pahole emits to
ensure the tag chain is PTR -> TYPE_TAG inner -> TYPE_TAG outer ->
struct sample, i.e. the innermost tag is closest to the pointer.
This exercises the type_tag ordering for both encodings: LLVM emits the
annotations as child DIEs in source order (reversed when building the
tag list), while GCC chains them via DW_AT_GNU_annotation already in BTF
order. The test runs with gcc and clang when they support btf_type_tag,
and is skipped when bpftool is unavailable.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
tests/btf_type_tag_order.sh | 179 ++++++++++++++++++++++++++++++++++++
1 file changed, 179 insertions(+)
create mode 100755 tests/btf_type_tag_order.sh
diff --git a/tests/btf_type_tag_order.sh b/tests/btf_type_tag_order.sh
new file mode 100755
index 000000000000..09d1ac346000
--- /dev/null
+++ b/tests/btf_type_tag_order.sh
@@ -0,0 +1,179 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+
+# Check that pahole preserves btf_type_tag order when emitting BTF from DWARF.
+
+source test_lib.sh
+
+outdir=$(make_tmpdir)
+
+# Comment this out to save test data.
+trap cleanup EXIT
+
+title_log "Check BTF type tag order."
+
+GCC=${GCC:-gcc}
+CLANG=${CLANG:-clang}
+PAHOLE=${PAHOLE:-pahole}
+BPFTOOL=${BPFTOOL:-bpftool}
+
+if ! command -v "$BPFTOOL" > /dev/null; then
+ info_log "skip: bpftool not available"
+ test_skip
+fi
+
+compiler_has_btf_type_tag()
+{
+ local compiler=$1
+
+ if ! command -v "$compiler" > /dev/null; then
+ return 1
+ fi
+
+ "$compiler" -x c -E -P - <<'EOF' 2>/dev/null | grep -qx 1
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+#if __has_attribute(btf_type_tag)
+1
+#else
+0
+#endif
+EOF
+}
+
+use_gcc=0
+if compiler_has_btf_type_tag "$GCC"; then
+ use_gcc=1
+fi
+
+use_clang=0
+if compiler_has_btf_type_tag "$CLANG"; then
+ use_clang=1
+fi
+
+if [ "$use_gcc" -eq 0 ] && [ "$use_clang" -eq 0 ]; then
+ error_log "Need gcc or clang with btf_type_tag support for test $0"
+ test_fail
+fi
+
+src=$(cat <<EOF
+#define __tag(x) __attribute__((btf_type_tag(#x)))
+
+struct sample {
+ int value;
+};
+
+struct sample __tag(outer) __tag(inner) *global_ptr;
+
+EOF
+)
+
+check_type_tag_order()
+{
+ local btf=$1
+ local dump
+
+ if ! dump=$("$BPFTOOL" btf dump file "$btf"); then
+ return 1
+ fi
+
+ printf '%s\n' "$dump" | awk '
+ function parse_id(line, m) {
+ if (match(line, /^\[([0-9]+)\]/, m))
+ return m[1]
+ return 0
+ }
+ function parse_name(line, m) {
+ if (match(line, /\047([^\047]*)\047/, m))
+ return m[1]
+ return ""
+ }
+ function parse_type(line, m) {
+ if (match(line, /type_id=([0-9]+)/, m))
+ return m[1]
+ return 0
+ }
+ function check_ptr(ptr, id, tags, seen) {
+ id = type[ptr]
+ while (id != 0 && !seen[id]) {
+ seen[id] = 1
+ if (kind[id] == "TYPE_TAG") {
+ tags = tags (tags == "" ? "" : " -> ") name[id]
+ id = type[id]
+ continue
+ }
+ if (kind[id] == "STRUCT" && name[id] == "sample") {
+ if (tags == "inner -> outer")
+ exit 0
+ candidates = candidates (candidates == "" ? "" : ", ") tags
+ }
+ return
+ }
+ }
+ /^\[[0-9]+\]/ {
+ id = parse_id($0)
+ kind[id] = $2
+ name[id] = parse_name($0)
+ type[id] = parse_type($0)
+ if (kind[id] == "PTR")
+ ptrs[++nr_ptrs] = id
+ }
+ END {
+ for (i = 1; i <= nr_ptrs; i++)
+ check_ptr(ptrs[i])
+ if (candidates != "") {
+ print "type tag order mismatch; expected inner -> outer, found " candidates > "/dev/stderr"
+ exit 1
+ }
+ print "could not find tagged pointer to struct sample" > "/dev/stderr"
+ exit 1
+ }'
+}
+
+run_test()
+{
+ local compiler=$1
+ local tmpobj=$2
+ local btf=$3
+
+ info_log "Testing with $compiler"
+
+ if ! echo "$src" | "$compiler" -g -c -x c -o "$tmpobj" - 2>/dev/null; then
+ error_log "Could not compile type tag order test with $compiler"
+ return 1
+ fi
+
+ if ! "$PAHOLE" --btf_features=+type_tag --btf_encode_detached="$btf" "$tmpobj" 2>/dev/null; then
+ error_log "Could not encode BTF for $tmpobj"
+ return 1
+ fi
+
+ if check_type_tag_order "$btf"; then
+ info_log " passed"
+ return 0
+ fi
+
+ error_log "BTF type tag order does not match expected order ($compiler)"
+ return 1
+}
+
+failed=0
+
+if [ "$use_gcc" -eq 1 ]; then
+ tmpobj=$(make_tmpobj)
+ btf=${tmpobj%.o}.btf
+ run_test "$GCC" "$tmpobj" "$btf" || failed=1
+fi
+
+if [ "$use_clang" -eq 1 ]; then
+ tmpobj=$(make_tmpobj)
+ btf=${tmpobj%.o}.btf
+ run_test "$CLANG" "$tmpobj" "$btf" || failed=1
+fi
+
+if [ "$failed" -eq 0 ]; then
+ test_pass
+else
+ test_fail
+fi
--
2.54.0
next prev parent reply other threads:[~2026-06-18 0:58 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-18 0:57 [PAHOLE v5 0/5] support for DW_TAG_GNU_annotation and fixes Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 1/5] btf_loader: Handle decl tag component_idx for parameters Vineet Gupta
2026-06-18 4:46 ` Emil Tsalapatis
2026-06-18 0:57 ` [PAHOLE v5 2/5] dwarf_loader: Extract die__add_btf_type_tag() helper [NFC] Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 3/5] dwarf_loader: Add support for DW_TAG_GNU_annotation Vineet Gupta
2026-06-18 0:57 ` [PAHOLE v5 4/5] tests: Support GCC in pfunct-btf-decl-tags test Vineet Gupta
2026-06-18 0:57 ` Vineet Gupta [this message]
2026-06-18 4:47 ` [PAHOLE v5 5/5] tests: Add btf_type_tag ordering test Emil Tsalapatis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260618005731.273181-6-vineet.gupta@linux.dev \
--to=vineet.gupta@linux.dev \
--cc=acme@kernel.org \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=david.faust@oracle.com \
--cc=dwarves@vger.kernel.org \
--cc=emil@etsalapatis.com \
--cc=jose.marchesi@oracle.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.