diff options
author | Patrick Mooney <pmooney@pfmooney.com> | 2017-08-14 23:17:17 +0000 |
---|---|---|
committer | Patrick Mooney <pmooney@pfmooney.com> | 2017-08-14 23:17:17 +0000 |
commit | 6ce9515e507bc9c47fd127589ef8734a84fed1c3 (patch) | |
tree | 81bdb54c1bdbe50f81daa194ccf9dd5b66916ec3 /usr/src/uts | |
parent | 801699355dea5fb4658b631b388aea1c1ca1926d (diff) | |
download | illumos-joyent-6ce9515e507bc9c47fd127589ef8734a84fed1c3.tar.gz |
OS-6066 want writable uregs[] in dtrace
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Alex Wilson <alex.wilson@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Diffstat (limited to 'usr/src/uts')
-rw-r--r-- | usr/src/uts/common/dtrace/dtrace.c | 55 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dtrace.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dtrace_impl.h | 3 | ||||
-rw-r--r-- | usr/src/uts/intel/dtrace/dtrace_isa.c | 151 | ||||
-rw-r--r-- | usr/src/uts/sparc/dtrace/dtrace_isa.c | 11 |
5 files changed, 195 insertions, 28 deletions
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c index 6ec6c5ae9d..f5ce5608aa 100644 --- a/usr/src/uts/common/dtrace/dtrace.c +++ b/usr/src/uts/common/dtrace/dtrace.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, Joyent, Inc. All rights reserved. + * Copyright (c) 2017, Joyent, Inc. * Copyright (c) 2012, 2014 by Delphix. All rights reserved. */ @@ -3545,6 +3545,34 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v, } } +static void +dtrace_dif_variable_write(dtrace_mstate_t *mstate, dtrace_state_t *state, + uint64_t v, uint64_t ndx, uint64_t data) +{ + switch (v) { + case DIF_VAR_UREGS: { + klwp_t *lwp; + + if (dtrace_destructive_disallow || + !dtrace_priv_proc_control(state, mstate)) { + return; + } + + if ((lwp = curthread->t_lwp) == NULL) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[CPU->cpu_id].cpuc_dtrace_illval = NULL; + return; + } + + dtrace_setreg(lwp->lwp_regs, ndx, data); + return; + } + + default: + DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); + return; + } +} typedef enum dtrace_json_state { DTRACE_JSON_REST = 1, @@ -6024,6 +6052,11 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate, regs[rd] = dtrace_dif_variable(mstate, state, id, 0); break; + case DIF_OP_STGA: + dtrace_dif_variable_write(mstate, state, r1, regs[r2], + regs[rd]); + break; + case DIF_OP_STGS: id = DIF_INSTR_VAR(instr); @@ -9407,6 +9440,15 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs, if (rd == 0) err += efunc(pc, "cannot write to %r0\n"); break; + case DIF_OP_STGA: + if (r1 > DIF_VAR_ARRAY_MAX) + err += efunc(pc, "invalid array %u\n", r1); + if (r2 >= nregs) + err += efunc(pc, "invalid register %u\n", r2); + if (rd >= nregs) + err += efunc(pc, "invalid register %u\n", rd); + dp->dtdo_destructive = 1; + break; case DIF_OP_LDGS: case DIF_OP_LDTS: case DIF_OP_LDLS: @@ -9752,12 +9794,23 @@ dtrace_difo_validate_helper(dtrace_difo_t *dp) break; case DIF_OP_LDTA: + if (v < DIF_VAR_OTHER_UBASE) { + err += efunc(pc, "illegal variable load\n"); + break; + } + /* FALLTHROUGH */ case DIF_OP_LDTS: case DIF_OP_LDGAA: case DIF_OP_LDTAA: err += efunc(pc, "illegal dynamic variable load\n"); break; + case DIF_OP_STGA: + if (v < DIF_VAR_OTHER_UBASE) { + err += efunc(pc, "illegal variable store\n"); + break; + } + /* FALLTHROUGH */ case DIF_OP_STTS: case DIF_OP_STGAA: case DIF_OP_STTAA: diff --git a/usr/src/uts/common/sys/dtrace.h b/usr/src/uts/common/sys/dtrace.h index 4ee1a94510..44ca7d8ae7 100644 --- a/usr/src/uts/common/sys/dtrace.h +++ b/usr/src/uts/common/sys/dtrace.h @@ -25,7 +25,7 @@ */ /* - * Copyright 2016 Joyent, Inc. + * Copyright 2017 Joyent, Inc. * Copyright (c) 2013 by Delphix. All rights reserved. */ @@ -189,6 +189,7 @@ typedef enum dtrace_probespec { #define DIF_OP_RLDX 77 /* rldx [r1], rd */ #define DIF_OP_XLATE 78 /* xlate xlrindex, rd */ #define DIF_OP_XLARG 79 /* xlarg xlrindex, rd */ +#define DIF_OP_STGA 80 /* stga var, ri, rd */ #define DIF_INTOFF_MAX 0xffff /* highest integer table offset */ #define DIF_STROFF_MAX 0xffff /* highest string table offset */ diff --git a/usr/src/uts/common/sys/dtrace_impl.h b/usr/src/uts/common/sys/dtrace_impl.h index de7d0d25fb..a55d0d7e1f 100644 --- a/usr/src/uts/common/sys/dtrace_impl.h +++ b/usr/src/uts/common/sys/dtrace_impl.h @@ -25,7 +25,7 @@ */ /* - * Copyright 2016 Joyent, Inc. + * Copyright 2017 Joyent, Inc. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -1262,6 +1262,7 @@ extern void dtrace_copyoutstr(uintptr_t, uintptr_t, size_t, volatile uint16_t *); extern void dtrace_getpcstack(pc_t *, int, int, uint32_t *); extern ulong_t dtrace_getreg(struct regs *, uint_t); +extern void dtrace_setreg(struct regs *, uint_t, ulong_t); extern uint64_t dtrace_getvmreg(uint_t, volatile uint16_t *); extern int dtrace_getstackdepth(int); extern void dtrace_getupcstack(uint64_t *, int); diff --git a/usr/src/uts/intel/dtrace/dtrace_isa.c b/usr/src/uts/intel/dtrace/dtrace_isa.c index f649473dfb..f52180b0c0 100644 --- a/usr/src/uts/intel/dtrace/dtrace_isa.c +++ b/usr/src/uts/intel/dtrace/dtrace_isa.c @@ -26,6 +26,7 @@ /* * Copyright (c) 2013, 2014 by Delphix. All rights reserved. + * Copyright (c) 2017 Joyent, Inc. */ #include <sys/dtrace_impl.h> @@ -546,39 +547,42 @@ dtrace_getstackdepth(int aframes) return (depth - aframes); } +#if defined(__amd64) +static const int dtrace_regmap[] = { + REG_GS, /* GS */ + REG_FS, /* FS */ + REG_ES, /* ES */ + REG_DS, /* DS */ + REG_RDI, /* EDI */ + REG_RSI, /* ESI */ + REG_RBP, /* EBP */ + REG_RSP, /* ESP */ + REG_RBX, /* EBX */ + REG_RDX, /* EDX */ + REG_RCX, /* ECX */ + REG_RAX, /* EAX */ + REG_TRAPNO, /* TRAPNO */ + REG_ERR, /* ERR */ + REG_RIP, /* EIP */ + REG_CS, /* CS */ + REG_RFL, /* EFL */ + REG_RSP, /* UESP */ + REG_SS /* SS */ +}; +#endif + + ulong_t dtrace_getreg(struct regs *rp, uint_t reg) { #if defined(__amd64) - int regmap[] = { - REG_GS, /* GS */ - REG_FS, /* FS */ - REG_ES, /* ES */ - REG_DS, /* DS */ - REG_RDI, /* EDI */ - REG_RSI, /* ESI */ - REG_RBP, /* EBP */ - REG_RSP, /* ESP */ - REG_RBX, /* EBX */ - REG_RDX, /* EDX */ - REG_RCX, /* ECX */ - REG_RAX, /* EAX */ - REG_TRAPNO, /* TRAPNO */ - REG_ERR, /* ERR */ - REG_RIP, /* EIP */ - REG_CS, /* CS */ - REG_RFL, /* EFL */ - REG_RSP, /* UESP */ - REG_SS /* SS */ - }; - if (reg <= SS) { - if (reg >= sizeof (regmap) / sizeof (int)) { + if (reg >= sizeof (dtrace_regmap) / sizeof (int)) { DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); return (0); } - reg = regmap[reg]; + reg = dtrace_regmap[reg]; } else { reg -= SS + 1; } @@ -651,6 +655,105 @@ dtrace_getreg(struct regs *rp, uint_t reg) #endif } +void +dtrace_setreg(struct regs *rp, uint_t reg, ulong_t val) +{ +#if defined(__amd64) + if (reg <= SS) { + ASSERT(reg < (sizeof (dtrace_regmap) / sizeof (int))); + + reg = dtrace_regmap[reg]; + } else { + reg -= SS + 1; + } + + switch (reg) { + case REG_RDI: + rp->r_rdi = val; + break; + case REG_RSI: + rp->r_rsi = val; + break; + case REG_RDX: + rp->r_rdx = val; + break; + case REG_RCX: + rp->r_rcx = val; + break; + case REG_R8: + rp->r_r8 = val; + break; + case REG_R9: + rp->r_r9 = val; + break; + case REG_RAX: + rp->r_rax = val; + break; + case REG_RBX: + rp->r_rbx = val; + break; + case REG_RBP: + rp->r_rbp = val; + break; + case REG_R10: + rp->r_r10 = val; + break; + case REG_R11: + rp->r_r11 = val; + break; + case REG_R12: + rp->r_r12 = val; + break; + case REG_R13: + rp->r_r13 = val; + break; + case REG_R14: + rp->r_r14 = val; + break; + case REG_R15: + rp->r_r15 = val; + break; + case REG_RSP: + rp->r_rsp = val; + break; + default: + DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); + return; + } + +#else /* defined(__amd64) */ + switch (reg) { + case EAX: + rp->r_eax = val; + break; + case ECX: + rp->r_ecx = val; + break; + case EDX: + rp->r_edx = val; + break; + case EBX: + rp->r_ebx = val; + break; + case ESP: + rp->r_esp = val; + break; + case EBP: + rp->r_ebp = val; + break; + case ESI: + rp->r_esi = val; + break; + case EDI: + rp->r_edi = val; + break; + default: + DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); + return; + } +#endif /* defined(__amd64) */ +} + static int dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) { diff --git a/usr/src/uts/sparc/dtrace/dtrace_isa.c b/usr/src/uts/sparc/dtrace/dtrace_isa.c index 20d9bc420b..541f733b06 100644 --- a/usr/src/uts/sparc/dtrace/dtrace_isa.c +++ b/usr/src/uts/sparc/dtrace/dtrace_isa.c @@ -24,7 +24,7 @@ * Use is subject to license terms. */ /* - * Copyright 2011 Joyent, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #include <sys/dtrace_impl.h> @@ -940,6 +940,15 @@ got_fp: return (value); } +/* ARGSUSED */ +int +dtrace_setreg(struct regs *rp, uint_t reg, ulong_t val) +{ + /* Not supported at this time */ + DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); + return (0); +} + /*ARGSUSED*/ uint64_t dtrace_getvmreg(uint_t ndx, volatile uint16_t *flags) |