[DTrace-devel] [PATCH 5/5] Work in Progress: Add support for strrchr()
eugene.loh at oracle.com
eugene.loh at oracle.com
Wed Aug 25 19:21:38 PDT 2021
From: Eugene Loh <eugene.loh at oracle.com>
This patch will be reworked once some other work -- still in
development and on which this patch will be rebased -- is finished.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
bpf/Build | 1 +
bpf/strrchr.S | 115 +++++++++++++++++++++++++++++++
libdtrace/dt_cg.c | 39 ++++++++++-
libdtrace/dt_dlibs.c | 1 +
test/unittest/funcs/tst.strchr.d | 1 -
5 files changed, 155 insertions(+), 2 deletions(-)
create mode 100644 bpf/strrchr.S
diff --git a/bpf/Build b/bpf/Build
index e7ecf9e5..9ef8552e 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -29,6 +29,7 @@ bpf_dlib_SOURCES = \
strcmp.S \
strchr.S \
strnlen.c \
+ strrchr.S \
substr.S \
varint.c
diff --git a/bpf/strrchr.S b/bpf/strrchr.S
new file mode 100644
index 00000000..5939d0e4
--- /dev/null
+++ b/bpf/strrchr.S
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define BPF_FUNC_probe_read 4
+
+/*
+ * char *dt_strrchr(char *s, uint64_t c, char *t) {
+ *
+ * c <<= 56;
+ *
+ * [%fp-8]=s
+ * [%fp-16]=c
+ * [%fp-24]=t
+ *
+ * r6 = dt_vint2int(s);
+ * r7 = dt_vint_size(r6);
+ *
+ * r8 = r6;
+ * Lloop:
+ * r8--;
+ * r3 = s[r7 + r8];
+ * r3 <<= 56;
+ * if (r3 == c) goto Lfound;
+ * if (r8 > 0) goto Lloop;
+ *
+ * return NULL;
+ *
+ * Lfound:
+ * r6 -= r8;
+ * r9 = dt_int2vint(r6, t);
+ * r7 += r8;
+ * bpf_probe_read(t + r9, r6, s + r7);
+ *
+ * r6 += r9;
+ * t[r6] = '\0';
+ *
+ * return t;
+ * }
+ */
+ .text
+ .align 4
+ .global dt_strrchr
+dt_strrchr :
+ lsh %r2, 56 /* c <<= 56 */
+
+ stxdw [%fp+-8], %r1 /* Spill s */
+ stxdw [%fp+-16], %r2 /* Spill c */
+ stxdw [%fp+-24], %r3 /* Spill t */
+
+ call dt_vint2int /* r6 = dt_vint2int(s) */
+
+ and %r0, 0xfffffff /* bound r6 */
+ lddw %r1, STRSZ
+ jle %r0, %r1, 1
+ mov %r0, %r1
+ mov %r6, %r0
+
+ mov %r1, %r6
+ call dt_vint_size /* r7 = dt_vint_size(r6) */
+ mov %r7, %r0
+
+ mov %r8, %r6 /* r8 = r6 */
+
+ ldxdw %r5, [%fp+-16]
+ lddw %r1, STRSZ
+.Lloop:
+ jsle %r8, 0, .Lnone
+ sub %r8, 1 /* r8-- */
+ mov %r4, %r7
+ add %r4, %r8
+ jge %r4, %r1, .Lloop
+ ldxdw %r3, [%fp+-8]
+ add %r3, %r4
+ ldxb %r3, [%r3+0] /* r3 = s[r7 + r8] */
+ lsh %r3, 56 /* r3 <<= 56 */
+ jeq %r3, %r5, .Lfound /* if (r3 == c) goto Lfound */
+ jgt %r8, 0, .Lloop /* if (r8 > 0) goto Lloop */
+
+.Lnone:
+ mov %r0, 0 /* return NULL */
+ exit
+
+.Lfound:
+ sub %r6, %r8 /* r6 -= r8 */
+ jge %r6, 0, 1
+ mov %r6, 0
+ and %r6, 0xffff
+ lddw %r1, STRSZ
+ jle %r6, %r1, 1
+ mov %r6, %r1
+
+ mov %r1, %r6
+ ldxdw %r2, [%fp+-24]
+ call dt_int2vint /* r9 = dt_int2vint(r6, t) */
+ mov %r9, %r0
+
+ add %r7, %r8 /* r7 += r8 */
+
+ ldxdw %r1, [%fp+-24]
+ add %r1, %r9
+ mov %r2, %r6
+ ldxdw %r3, [%fp+-8]
+ add %r3, %r7
+ call BPF_FUNC_probe_read /* bpf_probe_read(t + r9, r6, s + r7) */
+
+ add %r6, %r9 /* r6 += r9 */
+ ldxdw %r1, [%fp+-24]
+ add %r1, %r6 /* t[r6] = '\0' */
+ mov %r2, 0
+ stxb [%r1+0], %r2
+
+ ldxdw %r0, [%fp+-24] /* return t */
+ exit
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 3227c0a3..97e15d55 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3123,6 +3123,43 @@ dt_cg_subr_strchr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
TRACE_REGSET(" subr-strchr:End ");
}
+static void
+dt_cg_subr_strrchr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+ dt_ident_t *idp;
+ dt_node_t *str = dnp->dn_args;
+ dt_node_t *chr = str->dn_list;
+
+ TRACE_REGSET(" subr-strrchr:Begin");
+ dt_cg_node(str, dlp, drp);
+ dt_cg_check_notnull(dlp, drp, str->dn_reg);
+ dt_cg_node(chr, dlp, drp);
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, str->dn_reg));
+ dt_regset_free(drp, str->dn_reg);
+ emit(dlp, BPF_MOV_REG(BPF_REG_2, chr->dn_reg));
+ dt_regset_free(drp, chr->dn_reg);
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_3, BPF_REG_FP, DT_STK_DCTX));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_3, BPF_REG_3, DCTX_BUF));
+ emit(dlp, BPF_ALU64_IMM(BPF_SUB, BPF_REG_3, 512 + 8));
+
+ dt_regset_xalloc(drp, BPF_REG_0);
+ idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_strrchr");
+ assert(idp != NULL);
+ emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+ dt_regset_free_args(drp);
+ dnp->dn_reg = dt_regset_alloc(drp);
+ if (dnp->dn_reg == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ emit(dlp, BPF_MOV_REG(dnp->dn_reg, BPF_REG_0));
+ dt_regset_free(drp, BPF_REG_0);
+
+ TRACE_REGSET(" subr-strrchr:End ");
+}
+
static void
dt_cg_subr_substr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
@@ -3300,7 +3337,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
[DIF_SUBR_DIRNAME] = NULL,
[DIF_SUBR_CLEANPATH] = NULL,
[DIF_SUBR_STRCHR] = &dt_cg_subr_strchr,
- [DIF_SUBR_STRRCHR] = NULL,
+ [DIF_SUBR_STRRCHR] = &dt_cg_subr_strrchr,
[DIF_SUBR_STRSTR] = NULL,
[DIF_SUBR_STRTOK] = NULL,
[DIF_SUBR_SUBSTR] = &dt_cg_subr_substr,
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 459f2cc8..de60fdca 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -62,6 +62,7 @@ static const dt_ident_t dt_bpf_symbols[] = {
DT_BPF_SYMBOL(dt_strcmp, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_strchr, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_strnlen, DT_IDENT_SYMBOL),
+ DT_BPF_SYMBOL(dt_strrchr, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_substr, DT_IDENT_SYMBOL),
/* BPF maps */
DT_BPF_SYMBOL(aggs, DT_IDENT_PTR),
diff --git a/test/unittest/funcs/tst.strchr.d b/test/unittest/funcs/tst.strchr.d
index 9d8262df..a562b72e 100644
--- a/test/unittest/funcs/tst.strchr.d
+++ b/test/unittest/funcs/tst.strchr.d
@@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
-/* @@xfail: dtv2 */
#pragma D option quiet
--
2.18.4
More information about the DTrace-devel
mailing list