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:
Andrew Turner 2021-01-13 11:08:19 +00:00
parent 48ba9b2669
commit 28d945204e
4 changed files with 46 additions and 20 deletions

View File

@ -38,9 +38,15 @@
#define _C_LABEL(x) x #define _C_LABEL(x) x
#ifdef KDTRACE_HOOKS
#define DTRACE_NOP nop
#else
#define DTRACE_NOP
#endif
#define LENTRY(sym) \ #define LENTRY(sym) \
.text; .align 2; .type sym,#function; sym: \ .text; .align 2; .type sym,#function; sym: \
.cfi_startproc .cfi_startproc; DTRACE_NOP
#define ENTRY(sym) \ #define ENTRY(sym) \
.globl sym; LENTRY(sym) .globl sym; LENTRY(sym)
#define EENTRY(sym) \ #define EENTRY(sym) \

View File

@ -2466,6 +2466,8 @@ extern void dtrace_helpers_destroy(proc_t *);
#define B_DATA_MASK 0x00ffffff #define B_DATA_MASK 0x00ffffff
#define B_INSTR 0x14000000 #define B_INSTR 0x14000000
#define NOP_INSTR 0xd503201f
#define RET_INSTR 0xd65f03c0 #define RET_INSTR 0xd65f03c0
#define SUB_MASK 0xffc00000 #define SUB_MASK 0xffc00000

View File

@ -314,6 +314,11 @@ dtrace_invop_start(struct trapframe *frame)
return (0); return (0);
} }
if (invop == NOP_INSTR) {
frame->tf_elr += INSN_SIZE;
return (0);
}
if ((invop & B_MASK) == B_INSTR) { if ((invop & B_MASK) == B_INSTR) {
data = (invop & B_DATA_MASK); data = (invop & B_DATA_MASK);
/* The data is the number of 4-byte words to change the pc */ /* The data is the number of 4-byte words to change the pc */

View File

@ -110,28 +110,41 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
/* Look for stp (pre-indexed) operation */ /* Look for stp (pre-indexed) operation */
found = false; found = false;
for (; instr < limit; instr++) { /*
/* Some functions start with "stp xt1, xt2, [xn, <const>]!" */ * If the first instruction is a nop it's a specially marked
if ((*instr & LDP_STP_MASK) == STP_64) { * 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 * Some functions start with
* are past the function prolog. * "stp xt1, xt2, [xn, <const>]!"
*/ */
if (((*instr >> ADDR_SHIFT) & ADDR_MASK) == 31) if ((*instr & LDP_STP_MASK) == STP_64) {
found = true; /*
break; * 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>" * Some functions start with a "sub sp, sp, <const>"
* Sometimes the compiler will have a sub instruction that * Sometimes the compiler will have a sub instruction
* is not of the above type so don't stop if we see one. * 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 && if ((*instr & SUB_MASK) == SUB_INSTR &&
((*instr >> SUB_RN_SHIFT) & SUB_R_MASK) == 31) { ((*instr >> SUB_RD_SHIFT) & SUB_R_MASK) == 31 &&
found = true; ((*instr >> SUB_RN_SHIFT) & SUB_R_MASK) == 31) {
break; found = true;
break;
}
} }
} }