[DTrace-devel] [PATCH 1/2] Add support for strjoin() subroutine
Kris Van Hees
kris.van.hees at oracle.com
Thu Sep 2 08:33:56 PDT 2021
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
bpf/Build | 1 +
bpf/strjoin.S | 55 ++++++++++++++
libdtrace/dt_cg.c | 72 +++++++++++++++++--
libdtrace/dt_dlibs.c | 1 +
test/unittest/dif/strjoin.d | 6 +-
.../funcs/strjoin/tst.strjoin-nested.d | 34 +++++++++
.../funcs/strjoin/tst.strjoin-nested.r | 1 +
.../funcs/{ => strjoin}/tst.strjoin.d | 3 +-
.../funcs/{ => strjoin}/tst.strjoin.r | 0
9 files changed, 164 insertions(+), 9 deletions(-)
create mode 100644 bpf/strjoin.S
create mode 100644 test/unittest/funcs/strjoin/tst.strjoin-nested.d
create mode 100644 test/unittest/funcs/strjoin/tst.strjoin-nested.r
rename test/unittest/funcs/{ => strjoin}/tst.strjoin.d (80%)
rename test/unittest/funcs/{ => strjoin}/tst.strjoin.r (100%)
diff --git a/bpf/Build b/bpf/Build
index e7682bc7..d7dbbd5a 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -26,6 +26,7 @@ bpf_dlib_SOURCES = \
get_bvar.c \
get_tvar.c set_tvar.c \
probe_error.c \
+ strjoin.S \
strlen.c
bpf-check: $(objdir)/include/.dir.stamp
diff --git a/bpf/strjoin.S b/bpf/strjoin.S
new file mode 100644
index 00000000..2a19f2eb
--- /dev/null
+++ b/bpf/strjoin.S
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define DT_STRLEN_BYTES 2
+
+#define BPF_FUNC_probe_read_str 45
+
+/*
+ * void dt_strjoin(char *dst, const char *s1, const char *s2)
+ */
+ .text
+ .align 4
+ .global dt_strjoin
+ .type dt_strjoin, @function
+dt_strjoin:
+ mov %r9, %r1
+ mov %r7, %r2
+ mov %r8, %r3
+
+ mov %r1, %r7
+ call dt_strlen
+ mov %r6, %r0
+ add %r7, DT_STRLEN_BYTES
+
+ mov %r1, %r8
+ call dt_strlen
+ add %r6, %r0
+ add %r8, DT_STRLEN_BYTES
+
+ mov %r1, %r6
+ mov %r2, %r9
+ call dt_strlen_store
+ add %r9, DT_STRLEN_BYTES
+
+ lddw %r6, STRSZ
+ and %r6, 0xffffffff
+
+ mov %r1, %r9
+ mov %r2, %r6
+ mov %r3, %r7
+ call BPF_FUNC_probe_read_str
+ jslt %r0, 0, .L1
+ jslt %r0, 1, .L2
+ add %r9, %r0
+ sub %r9, 1
+.L2:
+ mov %r1, %r9
+ mov %r2, %r6
+ mov %r3, %r8
+ call BPF_FUNC_probe_read_str
+.L1:
+ exit
+ .size dt_strjoin, .-dt_strjoin
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index f9710a5e..b48b9f7b 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -753,20 +753,31 @@ dt_cg_strlen(dt_irlist_t *dlp, dt_regset_t *drp, int dst, int src)
size_t size = yypcb->pcb_hdl->dt_options[DTRACEOPT_STRSIZE];
uint_t lbl_ok = dt_irlist_label(dlp);
+ TRACE_REGSET(" strlen:Begin");
+
assert(idp != NULL);
if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
- emit(dlp, BPF_MOV_REG(BPF_REG_1, src));
- dt_regset_xalloc(drp, BPF_REG_0);
+ if (src != BPF_REG_1)
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, src));
+ if (dst != BPF_REG_0)
+ dt_regset_xalloc(drp, BPF_REG_0);
emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
dt_regset_free_args(drp);
emit(dlp, BPF_BRANCH_IMM(BPF_JLE, BPF_REG_0, size, lbl_ok));
emit(dlp, BPF_MOV_IMM(BPF_REG_0, size));
- emitl(dlp, lbl_ok,
- BPF_MOV_REG(dst, BPF_REG_0));
- dt_regset_free(drp, BPF_REG_0);
+
+ if (dst != BPF_REG_0) {
+ emitl(dlp, lbl_ok,
+ BPF_MOV_REG(dst, BPF_REG_0));
+ dt_regset_free(drp, BPF_REG_0);
+ } else
+ emitl(dlp, lbl_ok,
+ BPF_NOP());
+
+ TRACE_REGSET(" strlen:End ");
}
static void
@@ -3089,6 +3100,55 @@ dt_cg_subr_strlen(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
TRACE_REGSET(" subr-strlen:End ");
}
+static void
+dt_cg_subr_strjoin(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+ dt_node_t *s1 = dnp->dn_args;
+ dt_node_t *s2 = s1->dn_list;
+ dt_ident_t *idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_strjoin");
+
+ assert(idp != NULL);
+
+ TRACE_REGSET(" subr-strjoin:Begin");
+
+ dt_cg_node(s1, dlp, drp);
+ dt_cg_check_notnull(dlp, drp, s1->dn_reg);
+ dt_cg_node(s2, dlp, drp);
+ dt_cg_check_notnull(dlp, drp, s2->dn_reg);
+
+ /*
+ * We can re-use the register from s1 for our result. The result needs
+ * be be a temporary string, so we need to allocate one.
+ */
+ dnp->dn_reg = dt_regset_alloc(drp);
+ if (dnp->dn_reg == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dt_node_tstring(dnp, dt_cg_tstring_alloc());
+
+ emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_FP, DT_STK_DCTX));
+ emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, dnp->dn_reg, DCTX_MEM));
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, dnp->dn_tstring->dn_value));
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, dnp->dn_reg));
+ emit(dlp, BPF_MOV_REG(BPF_REG_2, s1->dn_reg));
+ dt_regset_free(drp, s1->dn_reg);
+ if (s1->dn_tstring)
+ dt_cg_tstring_free(s1->dn_tstring->dn_value);
+ emit(dlp, BPF_MOV_REG(BPF_REG_3, s2->dn_reg));
+ dt_regset_free(drp, s2->dn_reg);
+ if (s2->dn_tstring)
+ dt_cg_tstring_free(s2->dn_tstring->dn_value);
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+ dt_regset_free_args(drp);
+ dt_regset_free(drp, BPF_REG_0);
+
+ TRACE_REGSET(" subr-strjoin:End ");
+}
+
typedef void dt_cg_subr_f(dt_node_t *, dt_irlist_t *, dt_regset_t *);
static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
@@ -3115,7 +3175,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
[DIF_SUBR_GETMAJOR] = NULL,
[DIF_SUBR_GETMINOR] = NULL,
[DIF_SUBR_DDI_PATHNAME] = NULL,
- [DIF_SUBR_STRJOIN] = NULL,
+ [DIF_SUBR_STRJOIN] = dt_cg_subr_strjoin,
[DIF_SUBR_LLTOSTR] = NULL,
[DIF_SUBR_BASENAME] = NULL,
[DIF_SUBR_DIRNAME] = NULL,
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 04becfa6..771b7fe0 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -59,6 +59,7 @@ static const dt_ident_t dt_bpf_symbols[] = {
DT_BPF_SYMBOL(dt_get_string, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_get_tvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_set_tvar, DT_IDENT_SYMBOL),
+ DT_BPF_SYMBOL(dt_strjoin, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_strnlen, DT_IDENT_SYMBOL),
/* BPF maps */
DT_BPF_SYMBOL(aggs, DT_IDENT_PTR),
diff --git a/test/unittest/dif/strjoin.d b/test/unittest/dif/strjoin.d
index e7834eb9..ee70dec8 100644
--- a/test/unittest/dif/strjoin.d
+++ b/test/unittest/dif/strjoin.d
@@ -1,6 +1,10 @@
-/* @@xfail: dtv2 */
BEGIN
{
trace(strjoin(probeprov, probename));
exit(0);
}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/funcs/strjoin/tst.strjoin-nested.d b/test/unittest/funcs/strjoin/tst.strjoin-nested.d
new file mode 100644
index 00000000..84ba459c
--- /dev/null
+++ b/test/unittest/funcs/strjoin/tst.strjoin-nested.d
@@ -0,0 +1,34 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Nested strjoin() works
+ *
+ * SECTION: Actions and Subroutines/strjoin()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(strjoin(
+ strjoin(
+ strjoin(probeprov, ":"),
+ strjoin(probemod, ":")
+ ),
+ strjoin(
+ strjoin(probefunc, ":"),
+ probename
+ )
+ ));
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/funcs/strjoin/tst.strjoin-nested.r b/test/unittest/funcs/strjoin/tst.strjoin-nested.r
new file mode 100644
index 00000000..748852fb
--- /dev/null
+++ b/test/unittest/funcs/strjoin/tst.strjoin-nested.r
@@ -0,0 +1 @@
+dtrace:::BEGIN
diff --git a/test/unittest/funcs/tst.strjoin.d b/test/unittest/funcs/strjoin/tst.strjoin.d
similarity index 80%
rename from test/unittest/funcs/tst.strjoin.d
rename to test/unittest/funcs/strjoin/tst.strjoin.d
index beec500c..f52443bd 100644
--- a/test/unittest/funcs/tst.strjoin.d
+++ b/test/unittest/funcs/strjoin/tst.strjoin.d
@@ -1,10 +1,9 @@
/*
* Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
-/* @@xfail: dtv2 */
#pragma D option quiet
diff --git a/test/unittest/funcs/tst.strjoin.r b/test/unittest/funcs/strjoin/tst.strjoin.r
similarity index 100%
rename from test/unittest/funcs/tst.strjoin.r
rename to test/unittest/funcs/strjoin/tst.strjoin.r
--
2.33.0
More information about the DTrace-devel
mailing list