[DTrace-devel] [External] : [PATCH 7/7] test: add dtrace provider probe placement test for lld-linked objects

Eslam Almorshdy via B4 Relay devnull+ealmorshdy.d-matrix.ai at kernel.org
Thu Oct 15 03:53:47 UTC 2026


From: Eslam Almorshdy <ealmorshdy at d-matrix.ai>

Check that the dtrace provider's BEGIN and END uprobes are registered
at the file offsets of BEGIN_probe() and END_probe(), computed through
the PT_LOAD segment that holds each, and that both probes fire.

With a GNU ld-linked libdtrace, the file offset and the distance from
the first segment coincide, so the test can tell them apart only when
libdtrace itself is linked with lld.  There it fails without the
previous patch, reporting the misplaced offsets after a 10-second
timeout instead of hanging.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Eslam Almorshdy <ealmorshdy at d-matrix.ai>
---
 test/unittest/begin/tst.begin-end-offset.r  |  1 +
 test/unittest/begin/tst.begin-end-offset.sh | 87 +++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+)

diff --git a/test/unittest/begin/tst.begin-end-offset.r b/test/unittest/begin/tst.begin-end-offset.r
new file mode 100644
index 00000000..2e9ba477
--- /dev/null
+++ b/test/unittest/begin/tst.begin-end-offset.r
@@ -0,0 +1 @@
+success
diff --git a/test/unittest/begin/tst.begin-end-offset.sh b/test/unittest/begin/tst.begin-end-offset.sh
new file mode 100755
index 00000000..d1c316f4
--- /dev/null
+++ b/test/unittest/begin/tst.begin-end-offset.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at
+# http://oss.oracle.com/licenses/upl.
+#
+# Check that dtrace places the uprobes for its BEGIN and END probes at the
+# file offsets of BEGIN_probe() and END_probe() in libdtrace, and that both
+# fire.
+#
+# The offset must be computed through the PT_LOAD segment that contains the
+# function.  The function's distance from the first segment is the
+# same only if that segment has p_vaddr == p_offset.  With an lld-linked
+# libdtrace (p_vaddr = p_offset + 0x1000 on x86_64) BEGIN is placed 0x1000
+# past BEGIN_probe(), never fires, and the session hangs.  With a GNU
+# ld-linked libdtrace both computations agree.
+#
+
+dtrace=$1
+events=/sys/kernel/debug/tracing/uprobe_events
+
+DIRNAME=$tmpdir/begin-end-offset.$$.$RANDOM
+mkdir -p $DIRNAME
+cd $DIRNAME
+
+$dtrace $dt_flags -qn 'BEGIN { printf("begin\n"); } tick-1s { exit(0); }
+    END { printf("end\n"); }' > out 2>&1 &
+pid=$!
+
+# Record the session's uprobes while it runs; BEGIN, a tick and END take
+# about a second.
+for i in $(seq 50); do
+	grep "^p:dt_${pid}_dtrace/" $events >> uprobes
+	kill -0 $pid 2> /dev/null || break
+	sleep 0.2
+done
+if kill -0 $pid 2> /dev/null; then
+	echo "ERROR: dtrace did not exit within 10 seconds (BEGIN never fired?)"
+	{ kill -9 $pid; wait $pid; } 2> /dev/null
+	# A killed session leaves its uprobes behind.
+	sleep 1
+	for prb in $(sed -n "s|^p:dt_${pid}_dtrace/\([A-Z]*\) .*|\1|p" $events); do
+		echo "-:dt_${pid}_dtrace/$prb" >> $events
+	done
+fi
+wait $pid 2> /dev/null
+
+# fileoff FILE SYMBOL: the file offset of SYMBOL, through its PT_LOAD
+fileoff() {
+	local v type off va pa filesz rest
+
+	v=$({ nm $1; nm -D $1; } 2> /dev/null |
+	    awk -v s=$2 '$3 == s { print "0x" $1; exit }')
+	[ -n "$v" ] || return
+	while read type off va pa filesz rest; do
+		if [ "$type" = LOAD ] && [ $((v)) -ge $((va)) ] &&
+		   [ $((v)) -lt $((va + filesz)) ]; then
+			echo $((v - va + off))
+			return
+		fi
+	done < <(readelf -lW $1)
+}
+
+status=0
+for prb in BEGIN END; do
+	spec=$(awk -v e=p:dt_${pid}_dtrace/$prb '$1 == e { print $2; exit }' uprobes)
+	file=${spec%:*}
+	want=$(fileoff "$file" ${prb}_probe)
+	if [ -z "$spec" ] || [ -z "$want" ]; then
+		echo "ERROR: dtrace:::$prb: uprobe '$spec', ${prb}_probe offset '$want'"
+		status=1
+	elif [ $((${spec##*:})) -ne $want ]; then
+		printf "ERROR: dtrace:::%s placed at %s in %s, want 0x%x\n" \
+		    $prb ${spec##*:} $file $want
+		status=1
+	fi
+done
+
+if ! grep -qx begin out || ! grep -qx end out; then
+	echo "ERROR: BEGIN and END did not both fire:"
+	cat out
+	status=1
+fi
+
+[ $status -eq 0 ] && echo success
+exit $status

-- 
2.55.0





More information about the DTrace-devel mailing list