]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: different probe trigger instruction for entry vs return
authorKris Van Hees <kris.van.hees@oracle.com>
Tue, 16 May 2017 13:59:32 +0000 (09:59 -0400)
committerKris Van Hees <kris.van.hees@oracle.com>
Tue, 23 May 2017 14:22:21 +0000 (10:22 -0400)
On x86_64, we cannot use the LOCK prefix byte to consistently cause an
invalid opcode trap for FBT return probes because the 'ret' instruction
may be followed by an instruction that can validly take the LOCK prefix.
So, we use a different trigger instruction (int3).

In order to make this possible, the functions to set and clear FBT
probes on x86_64 (dtrace_invop_add() and dtrace_invop_remove()) have
been modified to accept a 2nd argument that indicates the instruction
to patch the probe location with.  This is needed because FBT return
probes need a different instruction on x86_64 (LOCK prefix to force
an invalid opcode trap isn't safe because we do not know what
instruction may follow the "ret").

Orabug: 25949048
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Tomas Jedlicka <tomas.jedlicka@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
dtrace/fbt_x86_64.c
dtrace/sdt_x86_64.c

index 45eb7eb5ee7863efe71154f55225b4457dc3e6b1..7853963c91f699ee21cc3f71539be3f5c5a8c227 100644 (file)
@@ -32,7 +32,8 @@
 #include "dtrace_dev.h"
 #include "fbt_impl.h"
 
-#define FBT_PATCHVAL           0xf0
+#define FBT_ENTRY_PATCHVAL             0xf0
+#define FBT_RETURN_PATCHVAL            0xcc
 
 static uint8_t fbt_invop(struct pt_regs *regs)
 {
@@ -60,7 +61,8 @@ static uint8_t fbt_invop(struct pt_regs *regs)
 
 void fbt_provide_probe_arch(fbt_probe_t *fbp, int type, int stype)
 {
-       fbp->fbp_patchval = FBT_PATCHVAL;
+       fbp->fbp_patchval = type == FBT_ENTRY ? FBT_ENTRY_PATCHVAL
+                                             : FBT_RETURN_PATCHVAL;
        fbp->fbp_savedval = *fbp->fbp_patchpoint;
        fbp->fbp_rval = type == FBT_ENTRY ? DTRACE_INVOP_PUSH_BP
                                          : DTRACE_INVOP_RET;
@@ -68,13 +70,12 @@ void fbt_provide_probe_arch(fbt_probe_t *fbp, int type, int stype)
 
 void fbt_enable_arch(fbt_probe_t *fbp, dtrace_id_t id, void *arg)
 {
-       dtrace_invop_enable((uint8_t *)fbp->fbp_patchpoint);
+       dtrace_invop_enable(fbp->fbp_patchpoint, fbp->fbp_patchval);
 }
 
 void fbt_disable_arch(fbt_probe_t *fbp, dtrace_id_t id, void *arg)
 {
-       dtrace_invop_disable((uint8_t *)fbp->fbp_patchpoint,
-                            fbp->fbp_savedval);
+       dtrace_invop_disable(fbp->fbp_patchpoint, fbp->fbp_savedval);
 }
 
 int fbt_dev_init_arch(void)
index b8f1ef440f2b0729bb1e8e82d7126da36fe527cc..546cf30933acaccfa70adbd041834b2216d61cf5 100644 (file)
@@ -69,13 +69,12 @@ void sdt_provide_probe_arch(sdt_probe_t *sdp, struct module *mp, int idx)
 
 void sdt_enable_arch(sdt_probe_t *sdp, dtrace_id_t id, void *arg)
 {
-       dtrace_invop_enable((uint8_t *)sdp->sdp_patchpoint);
+       dtrace_invop_enable(sdp->sdp_patchpoint, sdp->sdp_patchval);
 }
 
 void sdt_disable_arch(sdt_probe_t *sdp, dtrace_id_t id, void *arg)
 {
-       dtrace_invop_disable((uint8_t *)sdp->sdp_patchpoint,
-                            sdp->sdp_savedval);
+       dtrace_invop_disable(sdp->sdp_patchpoint, sdp->sdp_savedval);
 }
 
 uint64_t sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,