Handle functions that use a nop in the arm64 fbt
To trace leaf asm functions we can insert a single nop instruction as the first instruction in a function and trigger off this. Reviewed by: gnn Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D28132
This commit is contained in:
parent
48ba9b2669
commit
28d945204e
@ -38,9 +38,15 @@
|
||||
|
||||
#define _C_LABEL(x) x
|
||||
|
||||
#ifdef KDTRACE_HOOKS
|
||||
#define DTRACE_NOP nop
|
||||
#else
|
||||
#define DTRACE_NOP
|
||||
#endif
|
||||
|
||||
#define LENTRY(sym) \
|
||||
.text; .align 2; .type sym,#function; sym: \
|
||||
.cfi_startproc
|
||||
.cfi_startproc; DTRACE_NOP
|
||||
#define ENTRY(sym) \
|
||||
.globl sym; LENTRY(sym)
|
||||
#define EENTRY(sym) \
|
||||
|
@ -2466,6 +2466,8 @@ extern void dtrace_helpers_destroy(proc_t *);
|
||||
#define B_DATA_MASK 0x00ffffff
|
||||
#define B_INSTR 0x14000000
|
||||
|
||||
#define NOP_INSTR 0xd503201f
|
||||
|
||||
#define RET_INSTR 0xd65f03c0
|
||||
|
||||
#define SUB_MASK 0xffc00000
|
||||
|
@ -314,6 +314,11 @@ dtrace_invop_start(struct trapframe *frame)
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (invop == NOP_INSTR) {
|
||||
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 */
|
||||
|
@ -110,28 +110,41 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
|
||||
|
||||
/* Look for stp (pre-indexed) operation */
|
||||
found = false;
|
||||
for (; instr < limit; instr++) {
|
||||
/* Some functions start with "stp xt1, xt2, [xn, <const>]!" */
|
||||
if ((*instr & LDP_STP_MASK) == STP_64) {
|
||||
/*
|
||||
* If the first instruction is a nop it's a specially marked
|
||||
* asm function. We only support a nop first as it's not a normal
|
||||
* part of the function prologue.
|
||||
*/
|
||||
if (*instr == NOP_INSTR)
|
||||
found = true;
|
||||
if (!found) {
|
||||
for (; instr < limit; instr++) {
|
||||
/*
|
||||
* Assume any other store of this type means we
|
||||
* are past the function prolog.
|
||||
* Some functions start with
|
||||
* "stp xt1, xt2, [xn, <const>]!"
|
||||
*/
|
||||
if (((*instr >> ADDR_SHIFT) & ADDR_MASK) == 31)
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if ((*instr & LDP_STP_MASK) == STP_64) {
|
||||
/*
|
||||
* Assume any other store of this type means we
|
||||
* are past the function prolog.
|
||||
*/
|
||||
if (((*instr >> ADDR_SHIFT) & ADDR_MASK) == 31)
|
||||
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;
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user