[DTrace-devel] [PATCH 1/2 v3] Add annotations for dctx->X and mst->X members
Kris Van Hees
kris.van.hees at oracle.com
Tue Mar 29 04:41:47 UTC 2022
Due to how certain code patterns are generated, it is not always
possible to capture accesses of dctx and mst members. But since
common uses do use predictable patterns, we provide annotations for
cases.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
libdtrace/dt_dis.c | 128 ++++++++++++++++++-----
test/unittest/disasm/tst.ann-dctx-mst.r | 6 ++
test/unittest/disasm/tst.ann-dctx-mst.sh | 32 ++++++
3 files changed, 138 insertions(+), 28 deletions(-)
create mode 100644 test/unittest/disasm/tst.ann-dctx-mst.r
create mode 100755 test/unittest/disasm/tst.ann-dctx-mst.sh
diff --git a/libdtrace/dt_dis.c b/libdtrace/dt_dis.c
index 792cc99e..bfd639c6 100644
--- a/libdtrace/dt_dis.c
+++ b/libdtrace/dt_dis.c
@@ -82,18 +82,20 @@ dt_dis_varname_off(const dtrace_difo_t *dp, uint_t off, uint_t scope, uint_t add
}
/*
- * Check if we are loading from the gvar, lvar, or strtab BPF map.
+ * Check if we are accessing the gvars, lvars, or strtab BPF map, or the DTrace
+ * machine state.
*
- * If we are loading a gvar or lvar, we want to report the variable name.
- * If we are loading a string constant, we want to report its value.
+ * If we are accessing the gvars or lvars map, we report the variable name.
+ * If we are accessing strtab map, we report its value.
+ * If we are accessing the DTrace machine state, we report the member name.
*
* For variables, the sequence of instructions we are looking for is:
* insn code dst src offset imm
* -2: ld dst %fp DT_STK_DCTX 00000000
* -1: ld dst dst DCTX_*VARS 00000000
- * 0: ld dst dst var_offset 00000000
- * 0: st dst src var_offset 00000000
- * 0: add dst 0 0 var_offset
+ * 0: ld dst dst offset 00000000 -or-
+ * 0: st dst src offset 00000000 -or-
+ * 0: add dst 0 0 offset
* where instruction 0 is the current instruction, which may be one
* of the three above cases. The three cases represent:
* - load by value
@@ -104,7 +106,17 @@ dt_dis_varname_off(const dtrace_difo_t *dp, uint_t off, uint_t scope, uint_t add
* insn code dst src offset imm
* -2: ld dst %fp DT_STK_DCTX 00000000
* -1: ld dst dst DCTX_STRTAB 00000000
- * 0: add dst 0 0 var_offset
+ * 0: add dst 0 0 offset
+ * where instruction 0 is the current instruction.
+ *
+ * For DTrace machine state members, the sequence of instructions we are
+ * looking for is:
+ * insn code dst src offset imm
+ * -2: ld dst %fp DT_STK_DCTX 00000000
+ * -1: ld dst dst DCTX_MST 00000000
+ * 0: ld dst dst offset 00000000 -or-
+ * 0: st dst src offset 00000000 -or-
+ * 0: add dst 0 0 offset
* where instruction 0 is the current instruction.
*/
static void
@@ -113,7 +125,7 @@ dt_dis_refname(const dtrace_difo_t *dp, const struct bpf_insn *in, uint_t addr,
{
__u8 ldcode = BPF_LDX | BPF_MEM | BPF_DW;
__u8 addcode = BPF_ALU64 | BPF_ADD | BPF_K;
- int dst, scope = -1, var_offset = -1;
+ int dst, scope = -1, offset = -1;
const char *str;
/* make sure in[-2] and in[-1] exist */
@@ -127,7 +139,7 @@ dt_dis_refname(const dtrace_difo_t *dp, const struct bpf_insn *in, uint_t addr,
scope = DIFV_SCOPE_GLOBAL;
else if (in[-1].off == DCTX_LVARS)
scope = DIFV_SCOPE_LOCAL;
- else if (in[-1].off != DCTX_STRTAB)
+ else if (in[-1].off != DCTX_STRTAB && in[-1].off != DCTX_MST)
goto out;
/* check preceding instructions */
@@ -141,7 +153,7 @@ dt_dis_refname(const dtrace_difo_t *dp, const struct bpf_insn *in, uint_t addr,
in[-1].imm != 0)
goto out;
- /* check the current instruction and read var_offset */
+ /* check the current instruction and read offset */
if (in->dst_reg != dst)
goto out;
if (in[-1].off == DCTX_STRTAB) {
@@ -156,21 +168,53 @@ dt_dis_refname(const dtrace_difo_t *dp, const struct bpf_insn *in, uint_t addr,
} else if (BPF_CLASS(in->code) == BPF_LDX &&
BPF_MODE(in->code) == BPF_MEM &&
in->src_reg == dst && in->imm == 0)
- var_offset = in->off;
+ offset = in->off;
else if (BPF_CLASS(in->code) == BPF_STX &&
BPF_MODE(in->code) == BPF_MEM &&
in->src_reg != dst && in->imm == 0)
- var_offset = in->off;
+ offset = in->off;
else if (in->code == addcode && in->src_reg == 0 && in->off == 0)
- var_offset = in->imm;
+ offset = in->imm;
else
goto out;
/* print name */
- str = dt_dis_varname_off(dp, var_offset, scope, addr);
- if (str != NULL)
- fprintf(fp, "%*s! %s%s", DT_DIS_PAD(n), "",
- scope == DIFV_SCOPE_LOCAL ? "this->" : "", str);
+ if (in[-1].off == DCTX_MST) {
+ static const char *mst_members[sizeof(dt_mstate_t)] =
+ {
+ [0 ... sizeof(dt_mstate_t) - 1] = NULL,
+ [DMST_EPID] = "epid",
+ [DMST_PRID] = "prid",
+ [DMST_CLID] = "clid",
+ [DMST_TAG] = "tag",
+ [DMST_ERRNO] = "syscall_errno",
+ [DMST_FAULT] = "fault",
+ [DMST_TSTAMP] = "tstamp",
+ [DMST_REGS] = "regs",
+ [DMST_ARG(0)] = "arg0",
+ [DMST_ARG(1)] = "arg1",
+ [DMST_ARG(2)] = "arg2",
+ [DMST_ARG(3)] = "arg3",
+ [DMST_ARG(4)] = "arg4",
+ [DMST_ARG(5)] = "arg5",
+ [DMST_ARG(6)] = "arg6",
+ [DMST_ARG(7)] = "arg7",
+ [DMST_ARG(8)] = "arg8",
+ [DMST_ARG(9)] = "arg9",
+ };
+
+ if (offset < 0 || offset >= sizeof(dt_mstate_t))
+ goto out;
+
+ str = mst_members[offset];
+ if (str != NULL)
+ fprintf(fp, "%*s! mst->%s", DT_DIS_PAD(n), "", str);
+ } else {
+ str = dt_dis_varname_off(dp, offset, scope, addr);
+ if (str != NULL)
+ fprintf(fp, "%*s! %s%s", DT_DIS_PAD(n), "",
+ scope == DIFV_SCOPE_LOCAL ? "this->" : "", str);
+ }
out:
fprintf(fp, "\n");
@@ -252,16 +296,43 @@ dt_dis_load(const dtrace_difo_t *dp, const char *name, uint_t addr,
n = fprintf(fp, "%-4s %s, [%s%+d]", name, reg(in->dst_reg),
reg(in->src_reg), in->off);
- if (in->code == (BPF_LDX | BPF_MEM | BPF_DW) &&
- in->src_reg == BPF_REG_FP &&
- in->off <= DT_STK_SPILL(0) &&
- in->off >= DT_STK_SPILL(DT_STK_NREGS) &&
- in->dst_reg == -(in->off - DT_STK_SPILL_BASE) / DT_STK_SLOT_SZ) {
- fprintf(fp, "%*s! restore %s\n", DT_DIS_PAD(n), "",
- reg(in->dst_reg));
- } else
- dt_dis_refname(dp, in, addr, n, fp);
+ if (in->code == (BPF_LDX | BPF_MEM | BPF_DW)) {
+ if (in->src_reg == BPF_REG_FP && in->off <= DT_STK_SPILL(0) &&
+ in->off >= DT_STK_SPILL(DT_STK_NREGS) &&
+ in->dst_reg == -(in->off - DT_STK_SPILL_BASE) /
+ DT_STK_SLOT_SZ) {
+ fprintf(fp, "%*s! restore %s\n", DT_DIS_PAD(n), "",
+ reg(in->dst_reg));
+ return 0;
+ } else if (addr > 1 &&
+ in[-1].code == (BPF_LDX | BPF_MEM | BPF_DW) &&
+ in[-1].src_reg == BPF_REG_FP &&
+ in[-1].dst_reg == in->src_reg &&
+ in[-1].off == DT_STK_DCTX &&
+ in->off >= 0 && in->off < DCTX_SIZE) {
+ static const char *dctx_member[DCTX_SIZE] = {
+ [0 ... DCTX_SIZE - 1] = NULL,
+ [DCTX_CTX] = "ctx",
+ [DCTX_ACT] = "act",
+ [DCTX_MST] = "mst",
+ [DCTX_BUF] = "buf",
+ [DCTX_MEM] = "mem",
+ [DCTX_STRTAB] = "strtab",
+ [DCTX_AGG] = "agg",
+ [DCTX_GVARS] = "gvars",
+ [DCTX_LVARS] = "lvars",
+ };
+ const char *s = dctx_member[in->off];
+
+ if (s != NULL) {
+ fprintf(fp, "%*s! dctx->%s\n",
+ DT_DIS_PAD(n), "", s);
+ return 0;
+ }
+ }
+ }
+ dt_dis_refname(dp, in, addr, n, fp);
return 0;
}
@@ -303,9 +374,10 @@ dt_dis_store(const dtrace_difo_t *dp, const char *name, uint_t addr,
in->src_reg == -(in->off - DT_STK_SPILL_BASE) / DT_STK_SLOT_SZ) {
fprintf(fp, "%*s! spill %s\n", DT_DIS_PAD(n), "",
reg(in->src_reg));
- } else
- dt_dis_refname(dp, in, addr, n, fp);
+ return 0;
+ }
+ dt_dis_refname(dp, in, addr, n, fp);
return 0;
}
diff --git a/test/unittest/disasm/tst.ann-dctx-mst.r b/test/unittest/disasm/tst.ann-dctx-mst.r
new file mode 100644
index 00000000..992fc8dc
--- /dev/null
+++ b/test/unittest/disasm/tst.ann-dctx-mst.r
@@ -0,0 +1,6 @@
+79 X X 0018 00000000 lddw %rX, [%rX+24] ! dctx->buf
+79 X X 0000 00000000 lddw %rX, [%rX+0] ! dctx->ctx
+79 X X 0038 00000000 lddw %rX, [%rX+56] ! dctx->gvars
+79 X X 0040 00000000 lddw %rX, [%rX+64] ! dctx->lvars
+79 X X 0010 00000000 lddw %rX, [%rX+16] ! dctx->mst
+79 X X 0018 00000000 lddw %rX, [%rX+24] ! mst->fault
diff --git a/test/unittest/disasm/tst.ann-dctx-mst.sh b/test/unittest/disasm/tst.ann-dctx-mst.sh
new file mode 100755
index 00000000..17df9217
--- /dev/null
+++ b/test/unittest/disasm/tst.ann-dctx-mst.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2022, 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.
+#/
+
+dtrace=$1
+
+$dtrace $dt_flags -xdisasm=8 -qSn '
+BEGIN
+{
+ gvar = arg0;
+ self->tvar = 22;
+ this->lvar = 333;
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}' 2>&1 | awk '/^NAME/ {
+ exit(0);
+ }
+
+ /! (dctx|mst)->/ {
+ sub(/^[^:]+: /, "");
+ sub(/ [0-9a] [0-9a] /, " X X ");
+ gsub(/%r[0-9]/, "%rX");
+ print;
+ }' | sort -u -k10
--
2.34.1
More information about the DTrace-devel
mailing list