commit b09fc46ccc343a461a255b6ae1fea14ab7180846
Author: Serhei Makarov <serhei@serhei.io>
Date:   Wed Jul 23 16:13:52 2025 -0400

    PR33045: fix for kernel 6.16.0 sched_process_exit change
    
    Kernel commit 3e816361e94a0e79b1aabf44abec552e9698b196
    adds a group_dead argument to sched_process_exit tracepoint.
    
    Create a new runtime/transport/autoconf-utrace-via-tracepoints2.c
    and STAPCONF_UTRACE_VIA_TRACEPOINTS2 option
    and adjust runtime/stp_utrace.c to use the updated API
    where appropriate.
    
    Signed-off-by: Serguei Makarov <smakarov@redhat.com>

diff --git a/buildrun.cxx b/buildrun.cxx
index 47cfb2e8d..aeff75575 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -448,6 +448,7 @@ compile_pass (systemtap_session& s)
   output_autoconf(s, o, cs, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL);
   output_autoconf(s, o, cs, "autoconf-kernel_read-new-args.c", "STAPCONF_KERNEL_READ_NEW_ARGS", NULL);
   output_autoconf(s, o, cs, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL);
+  output_autoconf(s, o, cs, "autoconf-utrace-via-tracepoints2.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS2", NULL);
   output_autoconf(s, o, cs, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL);
   output_autoconf(s, o, cs, "autoconf-twa_resume.c", "STAPCONF_TWA_RESUME", NULL);
   output_autoconf(s, o, cs, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL);
diff --git a/runtime/linux/autoconf-utrace-via-tracepoints2.c b/runtime/linux/autoconf-utrace-via-tracepoints2.c
new file mode 100644
index 000000000..b4e66c1ca
--- /dev/null
+++ b/runtime/linux/autoconf-utrace-via-tracepoints2.c
@@ -0,0 +1,81 @@
+/* variant of autoconf_utrace_via_tracepoints.c post
+   kernel commit 3e816361e94a0e79b1aabf44abec552e9698b196
+   adding group_dead argument to sched_process_exit */
+
+#include <linux/mm.h>
+#include <trace/events/sched.h>
+#include <trace/events/syscalls.h>
+#include <linux/task_work.h>
+
+// The utrace-less task_finder needs 5 specific tracepoints and
+// <linux/task_work.h>.
+
+// NB: in kernels which do have the requisite pieces, just unconfigured, then
+// everything below will compile just fine, only returning ENOSYS at runtime.
+// To get the compile-time error that autoconf needs, check it directly:
+#ifndef CONFIG_TRACEPOINTS
+#error "CONFIG_TRACEPOINTS is not enabled"
+#endif
+
+void __sched_process_fork(void *cb_data __attribute__((unused)),
+			  struct task_struct *parent __attribute__((unused)),
+			  struct task_struct *child __attribute__((unused)));
+
+void __sched_process_fork(void *cb_data __attribute__((unused)),
+			  struct task_struct *parent __attribute__((unused)),
+			  struct task_struct *child __attribute__((unused)))
+{
+	return;
+}
+
+void __sched_process_exit(void *cb_data __attribute__((unused)),
+			  struct task_struct *task __attribute__((unused)),
+			  bool group_dead __attribute__((unused)));
+void __sched_process_exit(void *cb_data __attribute__((unused)),
+			  struct task_struct *task __attribute__((unused)),
+			  bool group_dead __attribute__((unused)))
+{
+	return;
+}
+
+void __sched_process_exec(void *cb_data __attribute__ ((unused)),
+			  struct task_struct *task __attribute__((unused)),
+			  pid_t old_pid __attribute__((unused)),
+			  struct linux_binprm *bprm __attribute__((unused)));
+void __sched_process_exec(void *cb_data __attribute__ ((unused)),
+			  struct task_struct *task __attribute__((unused)),
+			  pid_t old_pid __attribute__((unused)),
+			  struct linux_binprm *bprm __attribute__((unused)))
+{
+	return;
+}
+
+void __sys_enter(void *cb_data __attribute__ ((unused)),
+		 struct pt_regs *regs __attribute__((unused)),
+		 long id __attribute__((unused)));
+void __sys_enter(void *cb_data __attribute__ ((unused)),
+		 struct pt_regs *regs __attribute__((unused)),
+		 long id __attribute__((unused)))
+{
+	return;
+}
+
+void __sys_exit(void *cb_data __attribute__ ((unused)),
+		struct pt_regs *regs __attribute__((unused)),
+		long ret __attribute__((unused)));
+void __sys_exit(void *cb_data __attribute__ ((unused)),
+		struct pt_regs *regs __attribute__((unused)),
+		long ret __attribute__((unused)))
+{
+	return;
+}
+
+void __autoconf_func(void);
+void __autoconf_func(void)        
+{
+	(void) register_trace_sched_process_fork(__sched_process_fork, NULL);
+	(void) register_trace_sched_process_exit(__sched_process_exit, NULL);
+	(void) register_trace_sched_process_exec(__sched_process_exec, NULL);
+	(void) register_trace_sys_enter(__sys_enter, NULL);
+	(void) register_trace_sys_exit(__sys_exit, NULL);
+}
diff --git a/runtime/linux/runtime.h b/runtime/linux/runtime.h
index bd9307385..44aab7b99 100644
--- a/runtime/linux/runtime.h
+++ b/runtime/linux/runtime.h
@@ -342,7 +342,7 @@ __noendbr void ibt_restore(u64 save)
 #include "../regs.c"
 #include "regs-ia64.c"
 
-#if (defined(STAPCONF_UTRACE_VIA_TRACEPOINTS))
+#if (defined(STAPCONF_UTRACE_VIA_TRACEPOINTS) || defined(STAPCONF_UTRACE_VIA_TRACEPOINTS2))
 #define HAVE_TASK_FINDER
 #include "task_finder.c"
 #else
diff --git a/runtime/stp_utrace.c b/runtime/stp_utrace.c
index 9ddd67ada..52b53bd83 100644
--- a/runtime/stp_utrace.c
+++ b/runtime/stp_utrace.c
@@ -13,7 +13,7 @@
 #ifndef _STP_UTRACE_C
 #define _STP_UTRACE_C
 
-#if (!defined(STAPCONF_UTRACE_VIA_TRACEPOINTS))
+#if (!defined(STAPCONF_UTRACE_VIA_TRACEPOINTS) && !defined(STAPCONF_UTRACE_VIA_TRACEPOINTS2))
 #error "STAPCONF_UTRACE_VIA_TRACEPOINTS must be defined."
 #endif
 
@@ -258,8 +258,14 @@ static const struct utrace_engine_ops utrace_detached_ops; /* forward decl */
 static void utrace_report_clone(void *cb_data __attribute__ ((unused)),
 				struct task_struct *task,
 				struct task_struct *child);
+#ifdef STAPCONF_UTRACE_VIA_TRACEPOINTS2
+static void utrace_report_death(void *cb_data __attribute__ ((unused)),
+				struct task_struct *task,
+				bool group_dead __attribute__ ((unused)));
+#else
 static void utrace_report_death(void *cb_data __attribute__ ((unused)),
 				struct task_struct *task);
+#endif
 static void utrace_report_syscall_entry(void *cb_data __attribute__ ((unused)),
 					struct pt_regs *regs, long id);
 static void utrace_report_syscall_exit(void *cb_data __attribute__ ((unused)),
@@ -2767,8 +2773,14 @@ static void utrace_finish_vfork(struct task_struct *task)
  * For this reason, utrace_release_task checks for the event bits that get
  * us here, and delays its cleanup for us to do.
  */
+#ifdef STAPCONF_UTRACE_VIA_TRACEPOINTS2
+static void utrace_report_death(void *cb_data __attribute__ ((unused)),
+				struct task_struct *task,
+				bool group_dead __attribute__ ((unused)))
+#else
 static void utrace_report_death(void *cb_data __attribute__ ((unused)),
 				struct task_struct *task)
+#endif
 {
 	struct utrace_bucket *bucket;
 	struct utrace *utrace;
