[DTrace-devel] [PATCH 4/4] uregs: Support for older kernels (without BPF pt_regs helper functions)
eugene.loh at oracle.com
eugene.loh at oracle.com
Thu May 18 20:15:17 UTC 2023
From: Eugene Loh <eugene.loh at oracle.com>
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
libdtrace/dt_cg.c | 113 +++++++++++++++++-
.../err.D_UNKNOWN.uregs_badkernelversion.d | 19 ---
.../err.D_UNKNOWN.uregs_badkernelversion.r | 2 -
.../err.D_UNKNOWN.uregs_badkernelversion.x | 13 --
.../err.D_UNKNOWN.uregs_toobig.aarch64.x | 9 --
.../err.D_UNKNOWN.uregs_toobig.x86_64.x | 9 --
test/unittest/arrays/tst.uregsarray-check.x | 13 --
test/unittest/arrays/tst.uregsarray.arm64.x | 17 +--
test/unittest/arrays/tst.uregsarray.x | 13 --
test/unittest/arrays/tst.uregsarray.x86_64.x | 17 +--
test/unittest/disasm/tst.vartab-bvar-uregs0.x | 13 --
11 files changed, 113 insertions(+), 125 deletions(-)
delete mode 100644 test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d
delete mode 100644 test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.r
delete mode 100755 test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x
delete mode 100755 test/unittest/arrays/tst.uregsarray-check.x
delete mode 100755 test/unittest/arrays/tst.uregsarray.x
delete mode 100755 test/unittest/disasm/tst.vartab-bvar-uregs0.x
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index c1690f11..d8c17fb8 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -4123,11 +4123,6 @@ dt_cg_uregs(unsigned int idx, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp
{
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
- /* ensure we can use the BPF task_pt_regs() helper */
- if (dtp->dt_bpfhelper[BPF_FUNC_get_current_task_btf] == BPF_FUNC_unspec
- || dtp->dt_bpfhelper[BPF_FUNC_task_pt_regs] == BPF_FUNC_unspec)
- dnerror(dnp, D_UNKNOWN, "uregs[] is not supported on this kernel\n");
-
/* check if out-of-bounds */
if (idx >= sizeof(dt_pt_regs) / sizeof(uint64_t)) {
@@ -4175,7 +4170,113 @@ dt_cg_uregs(unsigned int idx, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp
return;
}
- /* if in-bounds, look up pt_regs[] */
+ /* If in-bounds, look up pt_regs[]. */
+
+ if (dtp->dt_bpfhelper[BPF_FUNC_get_current_task_btf] == BPF_FUNC_unspec ||
+ dtp->dt_bpfhelper[BPF_FUNC_task_pt_regs] == BPF_FUNC_unspec) {
+
+ /*
+ * To get pt_regs[], we try to use two BPF helper functions, but
+ * they exist only on newer kernels. Therefore, we check if they
+ * exist.
+ *
+ * If they do not exist, we are forced to emulate them, which is
+ * tricky since they depend on kernel configuration.
+ *
+ * In kernel/trace/bpf_trace.c, we see bpf_task_pt_regs() returns
+ * task_pt_regs(task).
+ *
+ * In turn, task_pt_regs() is defined in files like
+ * arch/arm64/include/asm/processor.h
+ * arch/x86/include/asm/processor.h
+ *
+ * For a wide range of kernels, the configuration parameters will
+ * be identical to the values below.
+ */
+
+ size_t offset;
+
+ /* Get task->stack. */
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_task));
+ emit(dlp, BPF_MOV_REG(BPF_REG_3, BPF_REG_0));
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3,
+ dt_cg_ctf_offsetof("struct task_struct", "stack", NULL)));
+ emit(dlp, BPF_MOV_IMM(BPF_REG_2, sizeof(uint64_t)));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_SP));
+ emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel]));
+ dt_regset_free_args(drp);
+ dt_regset_free(drp, BPF_REG_0);
+ emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_FP, DT_STK_SP));
+ emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, dnp->dn_reg, 0));
+
+ /* Start computing the offset to get to pt_regs[idx]. */
+ offset = 0;
+
+#if defined(__amd64)
+
+#define MY_PAGE_SIZE 4096
+
+/* arch/x86/include/asm/page_64_types.h */
+#define MY_KASAN_STACK_ORDER 0 /* for CONFIG_KASAN not set */
+#define MY_THREAD_SIZE_ORDER (2 + MY_KASAN_STACK_ORDER)
+#define MY_THREAD_SIZE (MY_PAGE_SIZE << MY_THREAD_SIZE_ORDER)
+
+ offset += MY_THREAD_SIZE;
+
+#undef MY_PAGE_SIZE
+#undef MY_KASAN_STACK_ORDER
+#undef MY_THREAD_SIZE_ORDER
+#undef MY_THREAD_SIZE
+
+#elif defined(__aarch64__)
+
+/* arch/arm64/include/asm/memory.h */
+#define MY_KASAN_THREAD_SHIFT 0 /* for CONFIG_KASAN not set */
+#define MY_MIN_THREAD_SHIFT (14 + MY_KASAN_THREAD_SHIFT)
+#define MY_THREAD_SHIFT MY_MIN_THREAD_SHIFT
+#define MY_THREAD_SIZE (1 << MY_THREAD_SHIFT)
+
+ offset += MY_THREAD_SIZE;
+
+#undef MY_KASAN_THREAD_SHIFT
+#undef MY_MIN_THREAD_SHIFT
+#undef MY_THREAD_SHIFT
+#undef MY_THREAD_SIZE
+
+#else
+# error ISA not supported
+#endif
+
+ /*
+ * Back up by sizeof(struct pt_regs). Do not use sizeof(dt_pt_regs)
+ * since it can be smaller, at least on aarch64.
+ */
+ {
+ ctf_file_t *cfp = yypcb->pcb_hdl->dt_shared_ctf;
+ ctf_id_t type;
+
+ type = ctf_lookup_by_name(cfp, "struct pt_regs");
+ if (type == CTF_ERR)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+
+ offset -= ctf_type_size(cfp, type);
+ }
+
+ /* Add the offset for our particular pt_regs[] index. */
+ offset += (idx * sizeof(uint64_t));
+
+ /* Add the fully computed offset to the pointer in the register. */
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, offset));
+
+ /* Dereference it safely (the BPF verifier has no idea what it is). */
+ dt_cg_load_scalar(dnp, BPF_DW, sizeof(uint64_t), dlp, drp);
+
+ return;
+ }
+
if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
dt_regset_xalloc(drp, BPF_REG_0);
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d
deleted file mode 100644
index ed375348..00000000
--- a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Oracle Linux DTrace.
- * Copyright (c) 2023, 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.
- */
-
-/*
- * ASSERTION: uregs[] not supported on old kernels.
- *
- * SECTION: User Process Tracing/uregs Array
- */
-
-BEGIN
-{
- trace(uregs[R_SP]);
- exit(1);
-}
-
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.r b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.r
deleted file mode 100644
index 09024896..00000000
--- a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.r
+++ /dev/null
@@ -1,2 +0,0 @@
--- @@stderr --
-dtrace: failed to compile script test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d: [D_UNKNOWN] line 16: uregs[] is not supported on this kernel
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x
deleted file mode 100755
index 0274240f..00000000
--- a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
-
-if [ $MAJOR -lt 5 ]; then
- exit 0
-fi
-if [ $MAJOR -eq 5 -a $MINOR -lt 15 ]; then
- exit 0
-fi
-
-echo "no UNKNOWN-uregs problem on newer kernels"
-exit 2
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.x b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.x
index 7b9e620f..36074cb2 100755
--- a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.x
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.x
@@ -1,13 +1,4 @@
#!/bin/sh
-read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
-
-if [ $MAJOR -lt 5 ]; then
- exit 2
-fi
-if [ $MAJOR -eq 5 -a $MINOR -lt 15 ]; then
- exit 2
-fi
-
[ `uname -m` = "aarch64" ] && exit 0
exit 2
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.x b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.x
index bce4d6b3..69e36e70 100755
--- a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.x
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.x
@@ -1,13 +1,4 @@
#!/bin/sh
-read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
-
-if [ $MAJOR -lt 5 ]; then
- exit 2
-fi
-if [ $MAJOR -eq 5 -a $MINOR -lt 15 ]; then
- exit 2
-fi
-
[ `uname -m` = "x86_64" ] && exit 0
exit 2
diff --git a/test/unittest/arrays/tst.uregsarray-check.x b/test/unittest/arrays/tst.uregsarray-check.x
deleted file mode 100755
index 4fb7f8c1..00000000
--- a/test/unittest/arrays/tst.uregsarray-check.x
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
-
-if [ $MAJOR -gt 5 ]; then
- exit 0
-fi
-if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
- exit 0
-fi
-
-echo "no uregs on older kernels"
-exit 1
diff --git a/test/unittest/arrays/tst.uregsarray.arm64.x b/test/unittest/arrays/tst.uregsarray.arm64.x
index 635c2a86..36074cb2 100755
--- a/test/unittest/arrays/tst.uregsarray.arm64.x
+++ b/test/unittest/arrays/tst.uregsarray.arm64.x
@@ -1,15 +1,4 @@
-#!/bin/bash
+#!/bin/sh
-[ `uname -m` != "aarch64" ] && exit 2
-
-read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
-
-if [ $MAJOR -gt 5 ]; then
- exit 0
-fi
-if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
- exit 0
-fi
-
-echo "uregs[]: pt_regs[] lookup not implemented on older kernels"
-exit 1
+[ `uname -m` = "aarch64" ] && exit 0
+exit 2
diff --git a/test/unittest/arrays/tst.uregsarray.x b/test/unittest/arrays/tst.uregsarray.x
deleted file mode 100755
index e63a58bd..00000000
--- a/test/unittest/arrays/tst.uregsarray.x
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
-
-if [ $MAJOR -gt 5 ]; then
- exit 0
-fi
-if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
- exit 0
-fi
-
-echo "uregs[]: pt_regs[] lookup not implemented on older kernels"
-exit 1
diff --git a/test/unittest/arrays/tst.uregsarray.x86_64.x b/test/unittest/arrays/tst.uregsarray.x86_64.x
index 5441e564..69e36e70 100755
--- a/test/unittest/arrays/tst.uregsarray.x86_64.x
+++ b/test/unittest/arrays/tst.uregsarray.x86_64.x
@@ -1,15 +1,4 @@
-#!/bin/bash
+#!/bin/sh
-[ `uname -m` != "x86_64" ] && exit 2
-
-read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
-
-if [ $MAJOR -gt 5 ]; then
- exit 0
-fi
-if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
- exit 0
-fi
-
-echo "uregs[]: pt_regs[] lookup not implemented on older kernels"
-exit 1
+[ `uname -m` = "x86_64" ] && exit 0
+exit 2
diff --git a/test/unittest/disasm/tst.vartab-bvar-uregs0.x b/test/unittest/disasm/tst.vartab-bvar-uregs0.x
deleted file mode 100755
index 4fb7f8c1..00000000
--- a/test/unittest/disasm/tst.vartab-bvar-uregs0.x
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
-
-if [ $MAJOR -gt 5 ]; then
- exit 0
-fi
-if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
- exit 0
-fi
-
-echo "no uregs on older kernels"
-exit 1
--
2.18.4
More information about the DTrace-devel
mailing list