[DTrace-devel] [PATCH 3/6] dtrace: add 'probeoff' variable to record relative offset of probes
Alan Maguire
alan.maguire at oracle.com
Fri Jun 5 22:12:14 UTC 2026
Record probe offset in machine state and make it accesible
via 'probeoff' variable. Having this is valuable as it will
allow dynamic computation of runtime variable offsets by giving
us the base address of a library. For example, we can determine
the base address of the python libpython3 library via:
python$target:::function-entry
{
base_addr = uregs[R_PC] - probeoff;
...
This will handle ASLR and will work for specific targets and
system-wide probes.
Since uregs[R_PC] will give us the runtime address of the python
probe, subtracting probeoff will give us the relative address used
at attach time. For example if 0x7ff925cd7f0d is the uregs
program counter value and 0xd7f0d is the probeoff value, we now
know the library base address is 0x7ff925c00000.
Once we have this, dynamic resolution of variables becomes easy
because we just need the symbol table offset for the variable
and we can add the library base address computed as above.
Signed-off-by: Alan Maguire <alan.maguire at oracle.com>
---
bpf/get_bvar.c | 7 +++++++
include/dtrace/dif_defines.h | 1 +
libdtrace/dt_cg.c | 5 +++++
libdtrace/dt_dctx.h | 2 ++
libdtrace/dt_open.c | 2 ++
libdtrace/dt_prov_uprobe.c | 8 ++++++++
6 files changed, 25 insertions(+)
diff --git a/bpf/get_bvar.c b/bpf/get_bvar.c
index 99a6503d..2b53b7d1 100644
--- a/bpf/get_bvar.c
+++ b/bpf/get_bvar.c
@@ -203,6 +203,13 @@ noinline uint64_t dt_bvar_probedesc(const dt_dctx_t *dctx, uint32_t idx)
}
}
+noinline uint64_t dt_bvar_probeoff(const dt_dctx_t *dctx)
+{
+ dt_mstate_t *mst = dctx->mst;
+
+ return mst->proff;
+}
+
noinline uint64_t dt_bvar_stackdepth(const dt_dctx_t *dctx)
{
uint32_t bufsiz = (uint32_t) (uint64_t) (&STKSIZ);
diff --git a/include/dtrace/dif_defines.h b/include/dtrace/dif_defines.h
index a18614d2..edb98f06 100644
--- a/include/dtrace/dif_defines.h
+++ b/include/dtrace/dif_defines.h
@@ -163,6 +163,7 @@
#define DIF_VAR_ERRNO 0x0120
#define DIF_VAR_CURCPU 0x0121
#define DIF_VAR_EXECARGS 0x0122
+#define DIF_VAR_PROBEOFF 0x0123
#define DIF_SUBR_RAND 0
#define DIF_SUBR_MUTEX_OWNED 1
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index e97e9abc..1bd73e11 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -288,6 +288,11 @@ dt_cg_tramp_prologue_act(dt_pcb_t *pcb, dt_activity_t act)
emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, roundup(sizeof(dt_mstate_t), 8)));
emit(dlp, BPF_STORE(BPF_DW, BPF_REG_9, DCTX_BUF, BPF_REG_0));
+ /*
+ * dctx.mst->proff = 0;
+ */
+ emit(dlp, BPF_STORE_IMM(BPF_DW, BPF_REG_7, DMST_PROFF, 0));
+
/*
* mem = buf + roundup(dtp->dt_maxreclen, 8);
* // add %r0, roundup(dtp->dt_maxreclen,
diff --git a/libdtrace/dt_dctx.h b/libdtrace/dt_dctx.h
index 5bf21345..797c8fd2 100644
--- a/libdtrace/dt_dctx.h
+++ b/libdtrace/dt_dctx.h
@@ -30,6 +30,7 @@ typedef struct dt_mstate {
uint32_t tag; /* Tag (for future use) */
uint32_t scratch_top; /* Current top of scratch space */
int32_t syscall_errno; /* syscall errno */
+ uint64_t proff; /* Probe offset */
uint64_t specsize; /* speculation size */
uint64_t scalarizer; /* used to scalarize pointers */
uint64_t fault; /* DTrace fault flags */
@@ -44,6 +45,7 @@ typedef struct dt_mstate {
#define DMST_STID offsetof(dt_mstate_t, stid)
#define DMST_TAG offsetof(dt_mstate_t, tag)
#define DMST_SCRATCH_TOP offsetof(dt_mstate_t, scratch_top)
+#define DMST_PROFF offsetof(dt_mstate_t, proff)
#define DMST_ERRNO offsetof(dt_mstate_t, syscall_errno)
#define DMST_SPECSIZE offsetof(dt_mstate_t, specsize)
#define DMST_SCALARIZER offsetof(dt_mstate_t, scalarizer)
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 30b8758d..ca00788a 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -240,6 +240,8 @@ static const dt_ident_t _dtrace_globals[] = {
DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
{ "probeprov", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEPROV,
DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
+{ "probeoff", DT_IDENT_SCALAR, 0, DIF_VAR_PROBEOFF,
+ DT_ATTR_STABCMN, DT_VERS_2_0, &dt_idops_type, "uint64_t" },
{ "progenyof", DT_IDENT_FUNC, 0, DIF_SUBR_PROGENYOF,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "int(pid_t)" },
diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
index b1b852ce..d53b1e43 100644
--- a/libdtrace/dt_prov_uprobe.c
+++ b/libdtrace/dt_prov_uprobe.c
@@ -1392,6 +1392,14 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
*/
dt_cg_tramp_copy_regs(pcb);
+ /*
+ * Record the uprobe instrumentation offset in the probe context.
+ * This is the same object-relative offset passed to perf_event_open()
+ * as attr.probe_offset.
+ */
+ dt_cg_xsetx(dlp, NULL, DT_LBL_NONE, BPF_REG_0, upp->off);
+ emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_PROFF, BPF_REG_0));
+
/*
* pid probes.
*
--
2.43.5
More information about the DTrace-devel
mailing list