[DTrace-devel] [PATCH] Implement the ppid builtin D variable
eugene.loh at oracle.com
eugene.loh at oracle.com
Wed Sep 16 11:16:33 PDT 2020
From: Eugene Loh <eugene.loh at oracle.com>
---
bpf/get_bvar.c | 11 ++++++
libdtrace/dt_bpf.c | 49 +++++++++++++++++++++---
libdtrace/dt_dctx.h | 4 ++
test/unittest/variables/bvar/tst.ppid.d | 1 -
test/unittest/variables/bvar/tst.ppid2.d | 21 ++++++++++
5 files changed, 80 insertions(+), 6 deletions(-)
create mode 100644 test/unittest/variables/bvar/tst.ppid2.d
diff --git a/bpf/get_bvar.c b/bpf/get_bvar.c
index 9f091080..2f6a59cc 100644
--- a/bpf/get_bvar.c
+++ b/bpf/get_bvar.c
@@ -46,6 +46,17 @@ noinline uint64_t dt_get_bvar(dt_mstate_t *mst, uint32_t id)
return val & 0x00000000ffffffffUL;
}
+ case DIF_VAR_PPID: {
+ uint64_t ptr = bpf_get_current_task();
+ int32_t val = -1;
+
+ if (ptr == 0)
+ return -1;
+
+ bpf_probe_read((void *) &ptr, 8, (const void *) (ptr + mst->offparent));
+ bpf_probe_read((void *) &val, 4, (const void *) (ptr + mst->offtgid));
+ return (uint64_t) val;
+ }
case DIF_VAR_UID: {
uint64_t val = bpf_get_current_uid_gid();
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index 556acb22..3cc55213 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -82,6 +82,28 @@ create_gmap(dtrace_hdl_t *dtp, const char *name, enum bpf_map_type type,
return fd;
}
+static int
+get_task_offsets(dtrace_hdl_t *dtp, int *offparent, int *offtgid)
+{
+ ctf_id_t type;
+ ctf_membinfo_t ctm;
+
+ type = ctf_lookup_by_name(dtp->dt_shared_ctf, "struct task_struct");
+ if (type == CTF_ERR)
+ return -1;
+
+ if (ctf_member_info(dtp->dt_shared_ctf, type, "real_parent", &ctm)
+ == CTF_ERR)
+ return -1;
+ *offparent = ctm.ctm_offset / NBBY;
+
+ if (ctf_member_info(dtp->dt_shared_ctf, type, "tgid", &ctm) == CTF_ERR)
+ return -1;
+ *offtgid = ctm.ctm_offset / NBBY;
+
+ return 0;
+}
+
/*
* Create the global BPF maps that are shared between all BPF programs in a
* single tracing session:
@@ -134,8 +156,13 @@ int
dt_bpf_gmap_create(dtrace_hdl_t *dtp)
{
int gvarc, tvarc;
- int ci_mapfd;
+ int ci_mapfd, ci_memfd;
uint32_t key = 0;
+ size_t memsz = roundup(sizeof(dt_mstate_t), 8) + 8 +
+ roundup(dtp->dt_maxreclen, 8);
+ int icpu, ncpus = dtp->dt_conf.num_online_cpus;
+ int offparent = -1, offtgid = -1;
+ char *p;
/* If we already created the global maps, return success. */
if (dt_gmap_done)
@@ -159,10 +186,9 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
if (ci_mapfd == -1)
return -1; /* dt_errno is set for us */
- if (create_gmap(dtp, "mem", BPF_MAP_TYPE_PERCPU_ARRAY,
- sizeof(uint32_t),
- roundup(sizeof(dt_mstate_t), 8) + 8 +
- roundup(dtp->dt_maxreclen, 8), 1) == -1)
+ ci_memfd = create_gmap(dtp, "mem", BPF_MAP_TYPE_PERCPU_ARRAY,
+ sizeof(uint32_t), memsz, 1);
+ if (ci_memfd == -1)
return -1; /* dt_errno is set for us */
if (create_gmap(dtp, "strtab", BPF_MAP_TYPE_ARRAY,
@@ -182,6 +208,19 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
/* Populate the 'cpuinfo' map. */
dt_bpf_map_update(ci_mapfd, &key, dtp->dt_conf.cpus);
+ /* Write some task_struct offsets into mstate. */
+ if (get_task_offsets(dtp, &offparent, &offtgid))
+ return -1; /* FIXME: set dt_errno */
+ p = alloca(memsz * ncpus);
+ memset(p, 0, memsz * ncpus);
+ for (icpu = 0; icpu < ncpus; icpu++) {
+ dt_mstate_t *q = (dt_mstate_t *) (p + icpu * memsz);
+ q->offparent = offparent;
+ q->offtgid = offtgid;
+ }
+ /* FIXME; is this how to use dt_bpf_map_update for a per-CPU array? */
+ dt_bpf_map_update(ci_memfd, &key, p);
+
return 0;
}
diff --git a/libdtrace/dt_dctx.h b/libdtrace/dt_dctx.h
index 79ef7105..b9b1c460 100644
--- a/libdtrace/dt_dctx.h
+++ b/libdtrace/dt_dctx.h
@@ -18,6 +18,8 @@ typedef struct dt_mstate {
uint32_t tag; /* Tag (for future use) */
uint64_t fault; /* DTrace fault flags */
uint64_t tstamp; /* cached timestamp value */
+ uint32_t offparent; /* offset in task_struct to real_parent */
+ uint32_t offtgid; /* offset in task_struct to tgid */
#if 0
dt_pt_regs regs; /* CPU registers */
#endif
@@ -48,6 +50,8 @@ typedef struct dt_dctx {
#define DMST_TAG offsetof(dt_mstate_t, tag)
#define DMST_FAULT offsetof(dt_mstate_t, fault)
#define DMST_TSTAMP offsetof(dt_mstate_t, tstamp)
+#define DMST_OFFPARENT offsetof(dt_mstate_t, offparent)
+#define DMST_OFFTGID offsetof(dt_mstate_t, offtgid)
#define DMST_REGS offsetof(dt_mstate_t, regs)
#define DMST_ARG(n) offsetof(dt_mstate_t, argv[n])
diff --git a/test/unittest/variables/bvar/tst.ppid.d b/test/unittest/variables/bvar/tst.ppid.d
index e406b36f..87bc52da 100644
--- a/test/unittest/variables/bvar/tst.ppid.d
+++ b/test/unittest/variables/bvar/tst.ppid.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 */
/*
* ASSERTION: The 'ppid' variable can be accessed and is not -1.
diff --git a/test/unittest/variables/bvar/tst.ppid2.d b/test/unittest/variables/bvar/tst.ppid2.d
new file mode 100644
index 00000000..be95d033
--- /dev/null
+++ b/test/unittest/variables/bvar/tst.ppid2.d
@@ -0,0 +1,21 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2020, 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: The 'ppid' variable matches the scripting variable for BEGIN.
+ *
+ * SECTION: Variables/Built-in Variables/ppid
+ */
+
+#pragma D option quiet
+
+BEGIN {
+ trace(ppid);
+ trace($ppid);
+ exit(ppid == $ppid ? 0 : 1);
+}
+
--
2.18.4
More information about the DTrace-devel
mailing list