[DTrace-devel] [PATCH 2/6] Support storing variables by reference
eugene.loh at oracle.com
eugene.loh at oracle.com
Fri Mar 19 10:45:30 PDT 2021
From: Eugene Loh <eugene.loh at oracle.com>
Initial support for storing variables by reference -- that is,
by copying them via the dt_memcpy() routine. Ultimately, this
support will have to be expanded to include kernel and userspace
memory.
Note that dt_memcpy() is currently limited to 256 bytes.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
bpf/Build | 3 +-
libdtrace/dt_cg.c | 43 +++++++++++++++++--------
test/unittest/struct/tst.StructInside.d | 3 +-
3 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/bpf/Build b/bpf/Build
index f8d736e7..5133a2f2 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -25,8 +25,9 @@ bpf_dlib_SOURCES = \
agg_lqbin.c agg_qbin.c \
get_bvar.c \
get_tvar.c set_tvar.c \
+ memcpy.c \
probe_error.c \
- memcpy.c strnlen.c
+ strnlen.c
bpf-check: $(objdir)/include/.dir.stamp
$(BPFC) $(BPFCPPFLAGS) $(bpf_dlib_CPPFLAGS) $(BPFCFLAGS) -S \
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 9243f0a7..ab3fe761 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -656,6 +656,26 @@ dt_cg_fill_gap(dt_pcb_t *pcb, int gap)
emit(dlp, BPF_STORE_IMM(BPF_W, BPF_REG_9, off, 0));
}
+static void
+dt_cg_memcpy(dt_irlist_t *dlp, dt_regset_t *drp, int dst, int src, size_t size)
+{
+ dt_ident_t *idp;
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, dst));
+ emit(dlp, BPF_MOV_REG(BPF_REG_2, src));
+ emit(dlp, BPF_MOV_IMM(BPF_REG_3, size));
+ idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_memcpy");
+ assert(idp != NULL);
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+ dt_regset_free_args(drp);
+ /* FIXME: check BPF_REG_0 for error? */
+ dt_regset_free(drp, BPF_REG_0);
+}
+
static void
dt_cg_spill_store(int reg)
{
@@ -1851,19 +1871,9 @@ dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
else
size = dt_node_type_size(src);
- if (src->dn_flags & DT_NF_REF) {
-#ifdef FIXME
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
- dt_cg_setx(dlp, reg, size);
- instr = DIF_INSTR_COPYS(src->dn_reg, reg, dst->dn_reg);
- dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
- dt_regset_free(drp, reg);
-#else
- xyerror(D_UNKNOWN, "internal error -- cg cannot store "
- "values passed by ref\n");
-#endif
- } else {
+ if (src->dn_flags & DT_NF_REF)
+ dt_cg_memcpy(dlp, drp, dst->dn_reg, src->dn_reg, size);
+ else {
uint8_t sz;
if (dst->dn_flags & DT_NF_BITFIELD)
@@ -1919,7 +1929,12 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
emit(dlp, BPF_LOAD(BPF_DW, reg, BPF_REG_FP, DT_STK_DCTX));
emit(dlp, BPF_LOAD(BPF_DW, reg, reg, DCTX_GVARS));
- emit(dlp, BPF_STORE(BPF_DW, reg, idp->di_offset, src->dn_reg));
+ if ((src->dn_flags & DT_NF_REF) == 0)
+ emit(dlp, BPF_STORE(BPF_DW, reg, idp->di_offset, src->dn_reg));
+ else {
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, reg, idp->di_offset));
+ dt_cg_memcpy(dlp, drp, reg, src->dn_reg, idp->di_size);
+ }
dt_regset_free(drp, reg);
return;
}
diff --git a/test/unittest/struct/tst.StructInside.d b/test/unittest/struct/tst.StructInside.d
index 71b2a839..2e1a8218 100644
--- a/test/unittest/struct/tst.StructInside.d
+++ b/test/unittest/struct/tst.StructInside.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 */
/*
* ASSERTION:
--
2.18.4
More information about the DTrace-devel
mailing list