[DTrace-devel] [PATCH REVIEW] work: run under valgrind
Nick Alcock
nick.alcock at oracle.com
Thu Sep 9 04:14:04 PDT 2021
Running BEGIN/END probes under valgrind failed because these probes work
by dropping uprobes on DTrace itself, and uprobes fail if the uprobed
process is being valgrinded: the breakpoint instruction inserted by
uprobes is translated into VEX IR and then emulated by valgrind, and the
emulation is located at a different address than the address originally
used by the kernel: so the kernel has no idea it was a uprobe, and
passes the breakpoint through to dtrace itself, killing it with a
SIGTRAP.
The solution is to use the bizarrely-named VALGRIND_NON_SIMD_CALL0
request to call the probes when valgrind is in use. This asks valgrind
to invoke a function on the real CPU rather than the emulated one, which
invokes it from the right address, so the kernel spots the uprobe for
what it is. VALGRIND_NON_SIMD_CALL* has harsh and barely-documented
requirements on what it can be used to call, but our probe functions are
entirely empty, so we can be pretty sure it'll always work for us.
Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
Orabug: 32760574
---
dtrace.spec | 2 +-
libdtrace/dt_work.c | 11 +++++++++--
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/dtrace.spec b/dtrace.spec
index 9098570f849d..a4c0e097f7ee 100644
--- a/dtrace.spec
+++ b/dtrace.spec
@@ -46,7 +46,7 @@ License: Universal Permissive License (UPL), Version 1.0
Group: Development/Tools
Requires: cpp elfutils-libelf zlib libpcap
BuildRequires: glibc-headers bison flex zlib-devel elfutils-libelf-devel
-BuildRequires: glibc-static %{glibc32} wireshark libpcap-devel
+BuildRequires: glibc-static %{glibc32} wireshark libpcap-devel valgrind-devel
BuildRequires: kernel%{variant}-devel = %{build_kernel}
BuildRequires: gcc-bpf-unknown-none
BuildRequires: binutils-bpf-unknown-none
diff --git a/libdtrace/dt_work.c b/libdtrace/dt_work.c
index 108eef9ac6f4..ff2a2458ad57 100644
--- a/libdtrace/dt_work.c
+++ b/libdtrace/dt_work.c
@@ -18,6 +18,7 @@
#include <port.h>
#include <linux/perf_event.h>
#include <sys/epoll.h>
+#include <valgrind/valgrind.h>
void
BEGIN_probe(void)
@@ -109,7 +110,10 @@ dtrace_go(dtrace_hdl_t *dtp, uint_t cflags)
if (err)
return err;
- BEGIN_probe();
+ if (RUNNING_ON_VALGRIND)
+ VALGRIND_NON_SIMD_CALL0(BEGIN_probe);
+ else
+ BEGIN_probe();
dtp->dt_active = 1;
dtp->dt_beganon = dt_state_get_beganon(dtp);
@@ -141,7 +145,10 @@ dtrace_stop(dtrace_hdl_t *dtp)
if (dt_state_get_activity(dtp) < DT_ACTIVITY_DRAINING)
dt_state_set_activity(dtp, DT_ACTIVITY_DRAINING);
- END_probe();
+ if (RUNNING_ON_VALGRIND)
+ VALGRIND_NON_SIMD_CALL0(END_probe);
+ else
+ END_probe();
dtp->dt_stopped = 1;
dtp->dt_endedon = dt_state_get_endedon(dtp);
--
2.33.0.256.gb827f06fa9
More information about the DTrace-devel
mailing list