Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Jan 2015 23:14:49 +0000
From:      bugzilla-noreply@freebsd.org
To:        freebsd-dtrace@FreeBSD.org
Subject:   [Bug 195222] dtrace kernel sdt probes must always be anchored
Message-ID:  <bug-195222-32976-gDUE3Nju8o@https.bugs.freebsd.org/bugzilla/>
In-Reply-To: <bug-195222-32976@https.bugs.freebsd.org/bugzilla/>
References:  <bug-195222-32976@https.bugs.freebsd.org/bugzilla/>

next in thread | previous in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=195222

Mark Johnston <markj@FreeBSD.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |markj@FreeBSD.org
             Status|New                         |In Progress

--- Comment #1 from Mark Johnston <markj@FreeBSD.org> ---
I've done some work towards solving this problem, together with implementing
Solaris-style SDT probes. By the latter I'm referring to the technique of
overwriting SDT probe sites with NOPs until the probes are enabled.

The core of the change is the move from

#define SDT_PROBE(...)
        if (sdt_<probe identifier> != NULL)
                sdt_<probe identifier>(<args>);

to

#define SDT_PROBE(...)
        __dtrace_probe_<probe identifier>(<args>);

In the new implementation, we call a function directly instead of through a
pointer, and the call is unconditional.

The main challenge is in identifying probe sites (represented by struct
sdt_instance in my patch). We need to define the __dtrace_probe_* stub
functions so that the kernel will link, but we also want to be able to find all
of the calls to __dtrace_probe_* so that we know where the probe sites are
actually located.

Trying to do this after the kernel (or a kld) has been linked seems challenging
- the only way to find __dtrace_probe_* calls would be to disassemble the text
section and look for calls/jmps to the address of a __dtrace_probe_* stub. What
Solaris does instead is look for relocations against the __dtrace_probe_*
stubs, and handle them specially: instead of processing the relocation, the
target offset is overwritten with NOPs, and the location is recorded for use by
the SDT kernel code.

I've written a userland program, sdtconvert (better name suggestions are
welcome), which does exactly this. It is intended to be run against all object
files in a kld immediately prior to linking. It looks for the relocations
described above, overwrites the probe sites with NOPs, and records each probe
site in a linker set, sdt_instances_set. Each struct sdt_instance in the set
contains a pointer to the corresponding sdt_probe (filled in with a relocation
emitted by sdtconvert), and the offset of the probe site within the kld.

I've also changed sdt.ko to examine the sdt_instances set when it processes a
kld. For each instance, we use the kernel linker to look up the name of the
function containing the probe site, and create a probe with the correct
function name. sdtconvert has already overwritten the probe sites with NOPs, so
sdt.ko's responsibility is to insert/remove a breakpoint at the probe site
whenever the probe is enabled/disabled.

As a result I now get the following:

markj@charmander: /usr/home/markj $ sudo dtrace -l -P tcp
Password:
   ID   PROVIDER            MODULE                          FUNCTION NAME
36965        tcp            kernel                    tcp_do_segment
accept-established
36966        tcp            kernel                    tcp_do_segment
connect-established
36967        tcp            kernel                    tcp_do_segment
connect-refused
36968        tcp            kernel                         tcp_input receive
36969        tcp            kernel                        tcp_output send
36970        tcp            kernel                        tcp_output
connect-request
36971        tcp            kernel                  tcp_state_change
state-change
36972        tcp            kernel                          tcp_drop
state-change
36973        tcp            kernel                       tcp_respond send
36974        tcp            kernel                       tcp_respond
accept-refused

In particular, the function names are filled in automatically. Probes that
specify their own function name are left alone.

sdtconvert.c: https://github.com/markjdb/sdtconvert/blob/master/sdtconvert.c
current FreeBSD changes (includes sdtconvert integration):
http://people.freebsd.org/~markj/patches/sdt-proper/sdt-proper-1.diff

The FreeBSD changes are on branch 20141214-sdt-proper in
github.com/markjdb/freebsd.

Note that this is still a WIP; I haven't yet written the kernel code to
enable/disable probes by overwriting the probe site. But that's pretty
straightforward.

One thing I haven't figured out is how to handle compatibility. There are a
number of SDT probes that specify the module and/or function, even though
they're not supposed to. I'd like to rename them to avoid abusing the function
and module components, but that would obviously break any script which uses
these probes (though they aren't documented and mostly likely aren't widely
used). It's preferable to just leave them alone, but I'd also like to have a
new KPI for SDT probes that doesn't allow the module or function name to be
specified, and convert "correct" SDT providers (io, ip, tcp, udp, proc, sched,
...) to use them. Then the old SDT(9) KPI would be deprecated.

Note that the work done so far only supports amd64.

Any thoughts?

-- 
You are receiving this mail because:
You are the assignee for the bug.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-195222-32976-gDUE3Nju8o>