From 60d9ab808030ebcdc653dda0e460321b709627db Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Tue, 16 May 2017 09:59:32 -0400 Subject: [PATCH] dtrace: different probe trigger instruction for entry vs return 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 Reviewed-by: Tomas Jedlicka Acked-by: Nick Alcock --- dtrace/fbt_x86_64.c | 11 ++++++----- dtrace/sdt_x86_64.c | 5 ++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dtrace/fbt_x86_64.c b/dtrace/fbt_x86_64.c index 45eb7eb5ee78..7853963c91f6 100644 --- a/dtrace/fbt_x86_64.c +++ b/dtrace/fbt_x86_64.c @@ -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) diff --git a/dtrace/sdt_x86_64.c b/dtrace/sdt_x86_64.c index b8f1ef440f2b..546cf30933ac 100644 --- a/dtrace/sdt_x86_64.c +++ b/dtrace/sdt_x86_64.c @@ -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, -- 2.50.1