Skip to content

Commit

Permalink
work: run under valgrind
Browse files Browse the repository at this point in the history
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@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
Orabug: 32760574
  • Loading branch information
nickalcock authored and kvanhees committed Oct 8, 2021
1 parent f1d8646 commit c3f94d8
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 4 deletions.
4 changes: 2 additions & 2 deletions dtrace.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# spec file for package dtrace
#
# Oracle Linux DTrace.
# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2021, 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.

Expand Down Expand Up @@ -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
Expand Down
11 changes: 9 additions & 2 deletions libdtrace/dt_work.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <port.h>
#include <linux/perf_event.h>
#include <sys/epoll.h>
#include <valgrind/valgrind.h>

void
BEGIN_probe(void)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit c3f94d8

Please sign in to comment.