kinst: check for 'push %rbp' anywhere in the function

Currently kinst checks if only the first instruction is 'push %rbp',
essentially excluding functions that do push RBP, but not in the first
instruction. This patch modifies kinst to check for 'push %rbp', as
well, as a following 'pop %rbp', anywhere in the function. This behavior
also matches that of FBT.

Reviewed by:	markj
Approved by:	markj (mentor)
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D40283
This commit is contained in:
Christos Margiolis 2023-07-19 17:53:08 +03:00
parent 8ada3f78e6
commit ea89133dbc

View file

@ -22,6 +22,7 @@
#include "kinst.h"
#define KINST_PUSHL_RBP 0x55
#define KINST_POPL_RBP 0x5d
#define KINST_STI 0xfb
#define KINST_POPF 0x9d
@ -500,7 +501,8 @@ kinst_make_probe(linker_file_t lf, int symindx, linker_symval_t *symval,
dtrace_kinst_probedesc_t *pd;
const char *func;
int error, instrsize, n, off;
uint8_t *instr, *limit;
uint8_t *instr, *limit, *tmp;
bool push_found, pop_found;
pd = opaque;
func = symval->name;
@ -515,12 +517,21 @@ kinst_make_probe(linker_file_t lf, int symindx, linker_symval_t *symval,
return (0);
/*
* Ignore functions not beginning with the usual function prologue.
* These might correspond to exception handlers with which we should not
* meddle. This does however exclude functions which can be safely
* traced, such as cpu_switch().
* Refuse to instrument functions lacking the usual frame pointer
* manipulations since they might correspond to exception handlers.
*/
if (*instr != KINST_PUSHL_RBP)
tmp = instr;
push_found = pop_found = false;
while (tmp < limit) {
if (*tmp == KINST_PUSHL_RBP)
push_found = true;
else if (*tmp == KINST_POPL_RBP)
pop_found = true;
if (push_found && pop_found)
break;
tmp += dtrace_instr_size(tmp);
}
if (!push_found || !pop_found)
return (0);
n = 0;