diff options
author | Andrew Turner <andrew@FreeBSD.org> | 2021-01-12 12:14:09 +0000 |
---|---|---|
committer | Andrew Turner <andrew@FreeBSD.org> | 2021-01-12 12:42:23 +0000 |
commit | c00ec4dab276414ccc8a0712dd2f836bb17349d7 (patch) | |
tree | f31ed86d5e42a1f10b5ce23f324eb3b534926930 /sys/cddl | |
parent | d0df1a2d54dcba438018f4be1d8bbaeac7e49d92 (diff) | |
download | src-c00ec4dab276414ccc8a0712dd2f836bb17349d7.tar.gz src-c00ec4dab276414ccc8a0712dd2f836bb17349d7.zip |
Handle using a sub instruction in the arm64 fbt
Some stack frames are too large for a store pair instruction we already
detect in the arm64 fbt code. Add support for handling subtracting the
stack pointer directly.
Sponsored by: Innovate UK
Diffstat (limited to 'sys/cddl')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h | 9 | ||||
-rw-r--r-- | sys/cddl/dev/dtrace/aarch64/dtrace_subr.c | 6 | ||||
-rw-r--r-- | sys/cddl/dev/fbt/aarch64/fbt_isa.c | 17 |
3 files changed, 31 insertions, 1 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h index 922c1a9bba9b..2bedd01cf3e7 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h @@ -2468,6 +2468,14 @@ extern void dtrace_helpers_destroy(proc_t *); #define RET_INSTR 0xd65f03c0 +#define SUB_MASK 0xffc00000 +#define SUB_INSTR 0xd1000000 +#define SUB_RD_SHIFT 0 +#define SUB_RN_SHIFT 5 +#define SUB_R_MASK 0x1f +#define SUB_IMM_SHIFT 10 +#define SUB_IMM_MASK 0xfff + #define LDP_STP_MASK 0xffc00000 #define STP_32 0x29800000 #define STP_64 0xa9800000 @@ -2488,6 +2496,7 @@ extern void dtrace_helpers_destroy(proc_t *); #define DTRACE_INVOP_STP 1 #define DTRACE_INVOP_RET 2 #define DTRACE_INVOP_B 3 +#define DTRACE_INVOP_SUB 4 #elif defined(__mips__) diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c index 2d59b29b850b..6646e51fc191 100644 --- a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c @@ -305,6 +305,12 @@ dtrace_invop_start(struct trapframe *frame) return (0); } + if ((invop & SUB_MASK) == SUB_INSTR) { + frame->tf_sp -= (invop >> SUB_IMM_SHIFT) & SUB_IMM_MASK; + frame->tf_elr += INSN_SIZE; + return (0); + } + if ((invop & B_MASK) == B_INSTR) { data = (invop & B_DATA_MASK); /* The data is the number of 4-byte words to change the pc */ diff --git a/sys/cddl/dev/fbt/aarch64/fbt_isa.c b/sys/cddl/dev/fbt/aarch64/fbt_isa.c index 9235af1a4c65..f15bc12291d3 100644 --- a/sys/cddl/dev/fbt/aarch64/fbt_isa.c +++ b/sys/cddl/dev/fbt/aarch64/fbt_isa.c @@ -121,6 +121,18 @@ fbt_provide_module_function(linker_file_t lf, int symindx, found = true; break; } + + /* + * Some functions start with a "sub sp, sp, <const>" + * Sometimes the compiler will have a sub instruction that + * is not of the above type so don't stop if we see one. + */ + if ((*instr & SUB_MASK) == SUB_INSTR && + ((*instr >> SUB_RD_SHIFT) & SUB_R_MASK) == 31 && + ((*instr >> SUB_RN_SHIFT) & SUB_R_MASK) == 31) { + found = true; + break; + } } if (!found) @@ -135,7 +147,10 @@ fbt_provide_module_function(linker_file_t lf, int symindx, fbt->fbtp_loadcnt = lf->loadcnt; fbt->fbtp_savedval = *instr; fbt->fbtp_patchval = FBT_PATCHVAL; - fbt->fbtp_rval = DTRACE_INVOP_STP; + if ((*instr & SUB_MASK) == SUB_INSTR) + fbt->fbtp_rval = DTRACE_INVOP_SUB; + else + fbt->fbtp_rval = DTRACE_INVOP_STP; fbt->fbtp_symindx = symindx; fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; |