aboutsummaryrefslogtreecommitdiff
path: root/sys/cddl
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2021-01-12 12:14:09 +0000
committerAndrew Turner <andrew@FreeBSD.org>2021-01-12 12:42:23 +0000
commitc00ec4dab276414ccc8a0712dd2f836bb17349d7 (patch)
treef31ed86d5e42a1f10b5ce23f324eb3b534926930 /sys/cddl
parentd0df1a2d54dcba438018f4be1d8bbaeac7e49d92 (diff)
downloadsrc-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.h9
-rw-r--r--sys/cddl/dev/dtrace/aarch64/dtrace_subr.c6
-rw-r--r--sys/cddl/dev/fbt/aarch64/fbt_isa.c17
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)];