From b005393ab0753e23edb2e58398a54918bae07058 Mon Sep 17 00:00:00 2001 From: dv Date: Sun, 3 Oct 2021 22:01:48 +0000 Subject: [PATCH] bt(5)/btrace(8): add support for str() Implement initial support for the str() function, which is used primarily to truncate or NUL-terminate strings from either cli args or args to tracepoints and syscalls. Current implementation only supports cli args and is primarily for compatability with bpftrace. Future work is needed once dt(4) supports builtin args other than long values. Adds a regress test and wires in argument-based tests again. ok mpi@ --- regress/usr.sbin/btrace/Makefile | 9 ++++-- regress/usr.sbin/btrace/print.bt | 4 +-- usr.sbin/btrace/bt.5 | 12 ++++++-- usr.sbin/btrace/bt_parse.y | 11 ++++++-- usr.sbin/btrace/bt_parser.h | 4 ++- usr.sbin/btrace/btrace.c | 47 ++++++++++++++++++++++++++++++-- usr.sbin/btrace/btrace.h | 3 +- 7 files changed, 75 insertions(+), 15 deletions(-) diff --git a/regress/usr.sbin/btrace/Makefile b/regress/usr.sbin/btrace/Makefile index a2382250585..54cfbabdd88 100644 --- a/regress/usr.sbin/btrace/Makefile +++ b/regress/usr.sbin/btrace/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.22 2021/09/16 10:54:35 anton Exp $ +# $OpenBSD: Makefile,v 1.23 2021/10/03 22:01:48 dv Exp $ BTRACE?= /usr/sbin/btrace ALLOWDT!= sysctl -n kern.allowdt @@ -11,6 +11,8 @@ BT_LANG_SCRIPTS= arithm beginend boolean comments delete exit \ precedence print read-map-after-clear staticv-empty \ syntaxerror +BT_ARG_LANG_SCRIPTS= staticv str + # scripts that use kernel probes BT_KERN_SCRIPTS= multiprobe @@ -22,11 +24,12 @@ run-$b: cd ${.CURDIR} && ${BTRACE} $b.bt 2>&1 | diff -u $b.ok /dev/stdin .endfor -b=staticv +.for b in ${BT_ARG_LANG_SCRIPTS} REGRESS_TARGETS+= run-$b run-$b: - ${BTRACE} ${.CURDIR}/$b.bt 42 1337 -2019 2>&1 | \ + cat ${.CURDIR}/$b.args | xargs ${BTRACE} ${.CURDIR}/$b.bt 2>&1 | \ diff -u ${.CURDIR}/$b.ok /dev/stdin +.endfor .for b in ${BT_KERN_SCRIPTS} REGRESS_TARGETS+= run-$b diff --git a/regress/usr.sbin/btrace/print.bt b/regress/usr.sbin/btrace/print.bt index 622f9c61a28..1a2e8358576 100644 --- a/regress/usr.sbin/btrace/print.bt +++ b/regress/usr.sbin/btrace/print.bt @@ -1,7 +1,7 @@ BEGIN { - $str = "string"; + $s = "string"; print(890); - print($str); + print($s); print(comm); } diff --git a/usr.sbin/btrace/bt.5 b/usr.sbin/btrace/bt.5 index a70f120fd11..3912c231adf 100644 --- a/usr.sbin/btrace/bt.5 +++ b/usr.sbin/btrace/bt.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bt.5,v 1.11 2021/04/21 10:22:36 mpi Exp $ +.\" $OpenBSD: bt.5,v 1.12 2021/10/03 22:01:48 dv Exp $ .\" .\" Copyright (c) 2019 Martin Pieuchot .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 21 2021 $ +.Dd $Mdocdate: October 3 2021 $ .Dt BT 5 .Os .Sh NAME @@ -154,11 +154,17 @@ entries in .It Fn printf "fmt" ... Print formatted string .Va fmt . +.It Fn str "$N" "[index]" +Return the string from argument +.Va $N , +truncated to +.Va index +characters (up to 64, the default) including a guaranteed NUL-terminator. .It Fn sum Returns the sum of all recorded values. .It Fn time timefmt Print timestamps using -.Xr strftime 3 +.Xr strftime 3 . .It Fn zero "@map" Set all values from .Va @map diff --git a/usr.sbin/btrace/bt_parse.y b/usr.sbin/btrace/bt_parse.y index faf2b05f119..f519efd87fd 100644 --- a/usr.sbin/btrace/bt_parse.y +++ b/usr.sbin/btrace/bt_parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: bt_parse.y,v 1.43 2021/09/09 12:09:11 mpi Exp $ */ +/* $OpenBSD: bt_parse.y,v 1.44 2021/10/03 22:01:48 dv Exp $ */ /* * Copyright (c) 2019-2021 Martin Pieuchot @@ -118,7 +118,7 @@ static int pflag; %token BUILTIN BEGIN END HZ IF /* Functions and Map operators */ %token F_DELETE F_PRINT -%token MFUNC FUNC0 FUNC1 FUNCN OP1 OP4 MOP0 MOP1 +%token MFUNC FUNC0 FUNC1 FUNCN OP1 OP2 OP4 MOP0 MOP1 %token STRING CSTRING %token NUMBER @@ -128,7 +128,7 @@ static int pflag; %type filter %type action stmt stmtblck stmtlist block %type pat vargs mentry mpat pargs staticv -%type expr term fterm variable factor +%type expr term fterm variable factor func %% grammar : /* empty */ @@ -221,8 +221,12 @@ factor : '(' expr ')' { $$ = $2; } | staticv | variable | mentry + | func ; +func : STR '(' staticv ')' { $$ = ba_new($3, B_AT_FN_STR); } + | STR '(' staticv ',' pat ')' { $$ = ba_op(B_AT_FN_STR, $3, $5); } + ; vargs : pat | vargs ',' pat { $$ = ba_append($1, $3); } @@ -714,6 +718,7 @@ lookup(char *s) { "print", F_PRINT, B_AC_PRINT }, { "printf", FUNCN, B_AC_PRINTF }, { "retval", BUILTIN, B_AT_BI_RETVAL }, + { "str", STR, B_AT_FN_STR }, { "sum", MOP1, B_AT_MF_SUM }, { "tid", BUILTIN, B_AT_BI_TID }, { "time", FUNC1, B_AC_TIME }, diff --git a/usr.sbin/btrace/bt_parser.h b/usr.sbin/btrace/bt_parser.h index 20fde72791e..6ba180c4379 100644 --- a/usr.sbin/btrace/bt_parser.h +++ b/usr.sbin/btrace/bt_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bt_parser.h,v 1.20 2021/09/09 09:53:11 mpi Exp $ */ +/* $OpenBSD: bt_parser.h,v 1.21 2021/10/03 22:01:48 dv Exp $ */ /* * Copyright (c) 2019-2021 Martin Pieuchot @@ -148,6 +148,8 @@ struct bt_arg { B_AT_BI_ARGS, B_AT_BI_RETVAL, + B_AT_FN_STR, /* str($1); str($1, 3); */ + B_AT_MF_COUNT, /* @map[key] = count() */ B_AT_MF_MAX, /* @map[key] = max(nsecs) */ B_AT_MF_MIN, /* @map[key] = min(pid) */ diff --git a/usr.sbin/btrace/btrace.c b/usr.sbin/btrace/btrace.c index 14a5212e2aa..e01569fb2d1 100644 --- a/usr.sbin/btrace/btrace.c +++ b/usr.sbin/btrace/btrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: btrace.c,v 1.57 2021/09/21 21:33:35 bluhm Exp $ */ +/* $OpenBSD: btrace.c,v 1.58 2021/10/03 22:01:48 dv Exp $ */ /* * Copyright (c) 2019 - 2021 Martin Pieuchot @@ -82,6 +82,7 @@ void rule_printmaps(struct bt_rule *); uint64_t builtin_nsecs(struct dt_evt *); const char *builtin_kstack(struct dt_evt *); const char *builtin_arg(struct dt_evt *, enum bt_argtype); +struct bt_arg *fn_str(struct bt_arg *, struct dt_evt *, char *); void stmt_eval(struct bt_stmt *, struct dt_evt *); void stmt_bucketize(struct bt_stmt *, struct dt_evt *); void stmt_clear(struct bt_stmt *); @@ -915,6 +916,10 @@ stmt_store(struct bt_stmt *bs, struct dt_evt *dtev) bv->bv_value = ba_new(ba2long(ba, dtev), B_AT_LONG); bv->bv_type = B_VT_LONG; break; + case B_AT_FN_STR: + bv->bv_value = ba_new(ba2str(ba, dtev), B_AT_STR); + bv->bv_type = B_VT_STR; + break; default: xabort("store not implemented for type %d", ba->ba_type); } @@ -922,6 +927,38 @@ stmt_store(struct bt_stmt *bs, struct dt_evt *dtev) debug("bv=%p var '%s' store (%p)\n", bv, bv_name(bv), bv->bv_value); } +/* + * String conversion { str($1); string($1, 3); } + * + * Since fn_str is currently only called in ba2str, *buf should be a pointer + * to the static buffer provided by ba2str. + */ +struct bt_arg * +fn_str(struct bt_arg *ba, struct dt_evt *dtev, char *buf) +{ + struct bt_arg *arg, *index; + ssize_t len = STRLEN; + + assert(ba->ba_type == B_AT_FN_STR); + + arg = (struct bt_arg*)ba->ba_value; + assert(arg != NULL); + + index = SLIST_NEXT(arg, ba_next); + if (index != NULL) { + /* Should have only 1 optional argument. */ + assert(SLIST_NEXT(index, ba_next) == NULL); + len = MINIMUM(ba2long(index, dtev) + 1, STRLEN); + } + + /* All negative lengths behave the same as a zero length. */ + if (len < 1) + return ba_new("", B_AT_STR); + + strlcpy(buf, ba2str(arg, dtev), len); + return ba_new(buf, B_AT_STR); +} + /* * Expression test: { if (expr) stmt; } */ @@ -1216,6 +1253,8 @@ ba_name(struct bt_arg *ba) return "args"; case B_AT_BI_RETVAL: return "retval"; + case B_AT_FN_STR: + return "str"; case B_AT_OP_PLUS: return "+"; case B_AT_OP_MINUS: @@ -1339,7 +1378,7 @@ ba2long(struct bt_arg *ba, struct dt_evt *dtev) const char * ba2str(struct bt_arg *ba, struct dt_evt *dtev) { - static char buf[sizeof("18446744073709551615")]; /* UINT64_MAX */ + static char buf[STRLEN]; struct bt_var *bv; const char *str; @@ -1400,6 +1439,9 @@ ba2str(struct bt_arg *ba, struct dt_evt *dtev) case B_AT_VAR: str = ba2str(ba_read(ba), dtev); break; + case B_AT_FN_STR: + str = (const char*)(fn_str(ba, dtev, buf))->ba_value; + break; case B_AT_OP_PLUS ... B_AT_OP_LOR: snprintf(buf, sizeof(buf), "%ld", ba2long(ba, dtev)); str = buf; @@ -1463,6 +1505,7 @@ ba2dtflags(struct bt_arg *ba) case B_AT_MF_MAX: case B_AT_MF_MIN: case B_AT_MF_SUM: + case B_AT_FN_STR: case B_AT_OP_PLUS ... B_AT_OP_LOR: break; default: diff --git a/usr.sbin/btrace/btrace.h b/usr.sbin/btrace/btrace.h index a45fa98cfc2..ded754e3d18 100644 --- a/usr.sbin/btrace/btrace.h +++ b/usr.sbin/btrace/btrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: btrace.h,v 1.9 2021/02/08 09:46:45 mpi Exp $ */ +/* $OpenBSD: btrace.h,v 1.10 2021/10/03 22:01:48 dv Exp $ */ /* * Copyright (c) 2019 - 2020 Martin Pieuchot @@ -53,6 +53,7 @@ struct hist *hist_increment(struct hist *, const char *, long); void hist_print(struct hist *, const char *); #define KLEN 512 /* # of characters in map key, contain a stack trace */ +#define STRLEN 64 /* maximum # of bytes to output via str() function */ /* printf.c */ int stmt_printf(struct bt_stmt *, struct dt_evt *); -- 2.20.1