Skip to content

Commit

Permalink
cc, bpf: separate final BPF program creation from linking and loading
Browse files Browse the repository at this point in the history
Some providers may need to do more complex code generaetion for the
probe BPF program trampoline.  The generation of trampoline code was
being done after BPF map creation, making it impossible for trampoline
code to use constructs that require data to be added to BPF maps.

The final BPF program handling has been changed to first create the
final programs, then create the BPF maps, and finally link and load the
BPF programs (performing the final relocations) and attaching them to
their probes.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Eugene Loh <eugene.loh@oracle.com>
  • Loading branch information
kvanhees committed Aug 29, 2023
1 parent d92d1bb commit bcf5f82
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 16 deletions.
49 changes: 36 additions & 13 deletions libdtrace/dt_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1085,12 +1085,11 @@ dt_bpf_reloc_error_prog(dtrace_hdl_t *dtp, dtrace_difo_t *dp)
}

int
dt_bpf_load_progs(dtrace_hdl_t *dtp, uint_t cflags)
dt_bpf_make_progs(dtrace_hdl_t *dtp, uint_t cflags)
{
dt_probe_t *prp;
dtrace_difo_t *dp;
dt_ident_t *idp = dt_dlib_get_func(dtp, "dt_error");
dtrace_optval_t dest_ok = DTRACEOPT_UNSET;

assert(idp != NULL);

Expand All @@ -1108,19 +1107,11 @@ dt_bpf_load_progs(dtrace_hdl_t *dtp, uint_t cflags)
idp->di_flags |= DT_IDFLG_CGREG; /* mark it as inline-ready */
dt_bpf_reloc_error_prog(dtp, dp);

/*
* Determine whether we can allow destructive actions.
*/
dtrace_getopt(dtp, "destructive", &dest_ok);

/*
* Now construct all the other programs.
*/
for (prp = dt_list_next(&dtp->dt_enablings); prp != NULL;
prp = dt_list_next(prp)) {
int fd;
int rc = -1;

/* Already done. */
if (prp == dtp->dt_error)
continue;
Expand All @@ -1132,9 +1123,43 @@ dt_bpf_load_progs(dtrace_hdl_t *dtp, uint_t cflags)
if (prp->prov->impl->prog_type == BPF_PROG_TYPE_UNSPEC)
continue;

dp = dt_program_construct(dtp, prp, cflags, NULL);
dp = dt_construct(dtp, prp, cflags, NULL);
if (dp == NULL)
return -1;

DT_DISASM_PROG(dtp, cflags, dp, stderr, NULL, prp->desc);

prp->difo = dp;
}

return 0;
}

int
dt_bpf_load_progs(dtrace_hdl_t *dtp, uint_t cflags)
{
dt_probe_t *prp;
dtrace_optval_t dest_ok = DTRACEOPT_UNSET;

/*
* Determine whether we can allow destructive actions.
*/
dtrace_getopt(dtp, "destructive", &dest_ok);

for (prp = dt_list_next(&dtp->dt_enablings); prp != NULL;
prp = dt_list_next(prp)) {
dtrace_difo_t *dp = prp->difo;
int fd;
int rc = -1;

if (dp == NULL)
continue;

if (dt_link(dtp, prp, dp, NULL) == -1)
return -1;

DT_DISASM_PROG_LINKED(dtp, cflags, dp, stderr, NULL, prp->desc);

if (dp->dtdo_flags & DIFOFLG_DESTRUCTIVE &&
dest_ok == DTRACEOPT_UNSET)
return dt_set_errno(dtp, EDT_DESTRUCTIVE);
Expand All @@ -1143,8 +1168,6 @@ dt_bpf_load_progs(dtrace_hdl_t *dtp, uint_t cflags)
if (fd == -1)
return -1;

dt_difo_free(dtp, dp);

if (prp->prov->impl->attach)
rc = prp->prov->impl->attach(dtp, prp, fd);

Expand Down
1 change: 1 addition & 0 deletions libdtrace/dt_bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ extern int dt_bpf_prog_load(enum bpf_prog_type prog_type,
const dtrace_difo_t *dp, uint32_t log_level,
char *log_buf, size_t log_buf_sz);
extern int dt_bpf_raw_tracepoint_open(const void *tp, int fd);
extern int dt_bpf_make_progs(struct dtrace_hdl *, uint_t);
extern int dt_bpf_load_progs(struct dtrace_hdl *, uint_t);
extern void dt_bpf_init_helpers(struct dtrace_hdl *dtp);

Expand Down
4 changes: 2 additions & 2 deletions libdtrace/dt_cc.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
return err ? NULL : rv;
}

static dtrace_difo_t *
dtrace_difo_t *
dt_construct(dtrace_hdl_t *dtp, dt_probe_t *prp, uint_t cflags, dt_ident_t *idp)
{
dt_pcb_t pcb;
Expand Down Expand Up @@ -1264,7 +1264,7 @@ dt_link_resolve(dtrace_hdl_t *dtp, dtrace_difo_t *dp)
}
}

static int
int
dt_link(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
dt_ident_t *idp)
{
Expand Down
4 changes: 4 additions & 0 deletions libdtrace/dt_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,10 @@ extern int dt_load_libs(dtrace_hdl_t *dtp);
extern void *dt_compile(dtrace_hdl_t *dtp, int context,
dtrace_probespec_t pspec, void *arg, uint_t cflags,
int argc, char *const argv[], FILE *fp, const char *s);
extern dtrace_difo_t *dt_construct(dtrace_hdl_t *dtp, struct dt_probe *prp,
uint_t cflags, dt_ident_t *idp);
extern int dt_link(dtrace_hdl_t *dtp, const struct dt_probe *prp,
dtrace_difo_t *dp, dt_ident_t *idp);
extern dtrace_difo_t *dt_program_construct(dtrace_hdl_t *dtp,
struct dt_probe *prp, uint_t cflags,
dt_ident_t *idp);
Expand Down
3 changes: 3 additions & 0 deletions libdtrace/dt_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,9 @@ dt_probe_destroy(dt_probe_t *prp)
else
dtp = yypcb->pcb_hdl;

if (prp->difo)
dt_difo_free(dtp, prp->difo);

if (prp->desc) {
dtp->dt_probes[prp->desc->id] = NULL;

Expand Down
3 changes: 2 additions & 1 deletion libdtrace/dt_probe.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2023, 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.
*/
Expand Down Expand Up @@ -54,6 +54,7 @@ typedef struct dt_probe {
dtrace_typeinfo_t *argv; /* output argument types */
int argc; /* output argument count */
dt_probe_instance_t *pr_inst; /* list of functions and offsets */
dtrace_difo_t *difo; /* BPF probe program */
} dt_probe_t;

extern dt_probe_t *dt_probe_lookup2(dt_provider_t *, const char *);
Expand Down
4 changes: 4 additions & 0 deletions libdtrace/dt_work.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ dtrace_go(dtrace_hdl_t *dtp, uint_t cflags)
setrlimit(RLIMIT_MEMLOCK, &rl);
}

/* Create the BPF programs. */
if (dt_bpf_make_progs(dtp, cflags) == -1)
return -1;

/* Create the global BPF maps. */
if (dt_bpf_gmap_create(dtp) == -1)
return -1;
Expand Down

0 comments on commit bcf5f82

Please sign in to comment.