bt(5)/btrace(8): add support for str()
authordv <dv@openbsd.org>
Sun, 3 Oct 2021 22:01:48 +0000 (22:01 +0000)
committerdv <dv@openbsd.org>
Sun, 3 Oct 2021 22:01:48 +0000 (22:01 +0000)
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
regress/usr.sbin/btrace/print.bt
usr.sbin/btrace/bt.5
usr.sbin/btrace/bt_parse.y
usr.sbin/btrace/bt_parser.h
usr.sbin/btrace/btrace.c
usr.sbin/btrace/btrace.h

index a238225..54cfbab 100644 (file)
@@ -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
index 622f9c6..1a2e835 100644 (file)
@@ -1,7 +1,7 @@
 BEGIN {
-       $str = "string";
+       $s = "string";
 
        print(890);
-       print($str);
+       print($s);
        print(comm);
 }
index a70f120..3912c23 100644 (file)
@@ -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 <mpi@openbsd.org>
 .\"
@@ -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
index faf2b05..f519efd 100644 (file)
@@ -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 <mpi@openbsd.org>
@@ -118,7 +118,7 @@ static int pflag;
 %token <v.i>           BUILTIN BEGIN END HZ IF
 /* Functions and Map operators */
 %token  <v.i>          F_DELETE F_PRINT
-%token <v.i>           MFUNC FUNC0 FUNC1 FUNCN OP1 OP4 MOP0 MOP1
+%token <v.i>           MFUNC FUNC0 FUNC1 FUNCN OP1 OP2 OP4 MOP0 MOP1
 %token <v.string>      STRING CSTRING
 %token <v.number>      NUMBER
 
@@ -128,7 +128,7 @@ static int pflag;
 %type  <v.filter>      filter
 %type  <v.stmt>        action stmt stmtblck stmtlist block
 %type  <v.arg>         pat vargs mentry mpat pargs staticv
-%type  <v.arg>         expr term fterm variable factor
+%type  <v.arg>         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 },
index 20fde72..6ba180c 100644 (file)
@@ -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 <mpi@openbsd.org>
@@ -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) */
index 14a5212..e01569f 100644 (file)
@@ -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 <mpi@openbsd.org>
@@ -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:
index a45fa98..ded754e 100644 (file)
@@ -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 <mpi@openbsd.org>
@@ -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 *);