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