Skip to content

Commit

Permalink
Add rodata support
Browse files Browse the repository at this point in the history
This patch provides for read-only data to be placed in its own memory
block (much like the .rodata ELF section).  It lays the groundwork for
future enhancements that support .rodata sections in precompiled BPF
code (as may be generated for static data items), and for the storage
of read-only data that is not constrained by the maximum string size.

Its first user will be the inet_ntoa6() implementation that needs to
store a read-only lookup table.

The string table can be considered a special case of read-only data
(as evidenced by the clear duplication of code between dt_rodata.c and
dt_strtab.c) and a future patch will convert the strtab implementation
to be a wrapper for a rodata-style memory block.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
kvanhees committed Aug 18, 2023
1 parent c5d1c19 commit 234064d
Show file tree
Hide file tree
Showing 12 changed files with 447 additions and 31 deletions.
1 change: 1 addition & 0 deletions libdtrace/Build
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ libdtrace-build_SOURCES = dt_aggregate.c \
dt_provider_sdt.c \
dt_provider_tp.c \
dt_regset.c \
dt_rodata.c \
dt_string.c \
dt_strtab.c \
dt_subr.c \
Expand Down
33 changes: 26 additions & 7 deletions libdtrace/dt_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,10 +695,17 @@ gmap_create_scratchmem(dtrace_hdl_t *dtp)
* String table map. This is a global map with a singleton element (key 0)
* that contains the entire string table as a concatenation of all unique
* strings (each terminated with a NUL byte). The string table size is taken
* from the DTrace consumer handle (dt_strlen). Extra memory is allocated as a
* memory block of zeros for initializing memory regions. Its size is at least
* the maximum string size to ensure the BPF verifier can validate all access
* requests for dynamic references to string constants.
* from the DTrace consumer handle (dt_strlen).
*
* The read-only data is appended to the string table, as is a memory block of
* zeros for initializing memory regions.
*
* In order to ensure the BPF verifier can validate all access requests for
* dynamic references to string constants, the size of the read-only data plus
* the size of the block of zeros must at least match the maximum string size.
* The size of the block of zeros must at least match the maximum read-only
* item size, and be large enough to satisfy all 0-initialization needs in all
* BPF programs being loaded for this tracing session.
*/
static int
gmap_create_strtab(dtrace_hdl_t *dtp)
Expand All @@ -711,13 +718,20 @@ gmap_create_strtab(dtrace_hdl_t *dtp)
int fd, rc, err;

dtp->dt_strlen = dt_strtab_size(dtp->dt_ccstab);
dtp->dt_zerooffset = P2ROUNDUP(dtp->dt_strlen, 8);
dtp->dt_rooffset = P2ROUNDUP(dtp->dt_strlen, 8);
dtp->dt_rosize = dt_rodata_size(dtp->dt_rodata);
dtp->dt_zerooffset = P2ROUNDUP(dtp->dt_rooffset + dtp->dt_rosize, 8);
dtp->dt_zerosize = 0;
sz = dt_rodata_max_item_size(dtp->dt_rodata);

/*
* Ensure the zero-filled memory at the end of the strtab is large
* enough to accomodate all needs for such a memory block.
* enough to accommodate all needs for such a memory block.
*/
dtp->dt_zerosize = strsize + 1;
if (dtp->dt_rosize < strsize + 1)
dtp->dt_zerosize = strsize + 1 - dtp->dt_rosize;
if (dtp->dt_zerosize < sz)
dtp->dt_zerosize = sz;
if (dtp->dt_zerosize < dtp->dt_maxdvarsize)
dtp->dt_zerosize = dtp->dt_maxdvarsize;
if (dtp->dt_zerosize < dtp->dt_maxtuplesize)
Expand All @@ -730,6 +744,7 @@ gmap_create_strtab(dtrace_hdl_t *dtp)
if (strtab == NULL)
return dt_set_errno(dtp, EDT_NOMEM);

/* Copy the string table data. */
dt_strtab_write(dtp->dt_ccstab, (dt_strtab_write_f *)dt_strtab_copystr,
strtab);

Expand All @@ -745,6 +760,10 @@ gmap_create_strtab(dtrace_hdl_t *dtp)
buf += len + 1;
}

/* Copy the read-only data. */
dt_rodata_write(dtp->dt_rodata, (dt_rodata_copy_f *)dt_rodata_copy,
strtab + dtp->dt_rooffset);

fd = create_gmap(dtp, "strtab", BPF_MAP_TYPE_ARRAY, sizeof(uint32_t),
sz, 1);
if (fd == -1)
Expand Down
40 changes: 21 additions & 19 deletions libdtrace/dt_bpf.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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 All @@ -19,25 +19,27 @@ struct dtrace_hdl;
extern "C" {
#endif

#define DT_CONST_EPID 1
#define DT_CONST_PRID 2
#define DT_CONST_CLID 3
#define DT_CONST_ARGC 4
#define DT_CONST_STBSZ 5
#define DT_CONST_STRSZ 6
#define DT_CONST_STKSIZ 7
#define DT_CONST_BOOTTM 8
#define DT_CONST_NSPEC 9
#define DT_CONST_NCPUS 10
#define DT_CONST_PC 11
#define DT_CONST_TUPSZ 12
#define DT_CONST_TASK_PID 13
#define DT_CONST_TASK_TGID 14
#define DT_CONST_EPID 1
#define DT_CONST_PRID 2
#define DT_CONST_CLID 3
#define DT_CONST_ARGC 4
#define DT_CONST_STBSZ 5
#define DT_CONST_STRSZ 6
#define DT_CONST_STKSIZ 7
#define DT_CONST_BOOTTM 8
#define DT_CONST_NSPEC 9
#define DT_CONST_NCPUS 10
#define DT_CONST_PC 11
#define DT_CONST_TUPSZ 12
#define DT_CONST_TASK_PID 13
#define DT_CONST_TASK_TGID 14
#define DT_CONST_TASK_REAL_PARENT 15
#define DT_CONST_TASK_COMM 16
#define DT_CONST_MUTEX_OWNER 17
#define DT_CONST_RWLOCK_CNTS 18
#define DT_CONST_ZERO_OFF 19
#define DT_CONST_TASK_COMM 16
#define DT_CONST_MUTEX_OWNER 17
#define DT_CONST_RWLOCK_CNTS 18
#define DT_CONST_RODATA_OFF 19
#define DT_CONST_RODATA_SIZE 20
#define DT_CONST_ZERO_OFF 21

#define DT_BPF_LOG_SIZE_DEFAULT (UINT32_MAX >> 8)
#define DT_BPF_LOG_SIZE_SMALL 4096
Expand Down
8 changes: 7 additions & 1 deletion libdtrace/dt_cc.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 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 @@ -2468,6 +2468,12 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
nrp->dofr_data = total_offset;
continue;
}
case DT_CONST_RODATA_OFF:
nrp->dofr_data = dtp->dt_rooffset;
continue;
case DT_CONST_RODATA_SIZE:
nrp->dofr_data = dtp->dt_rosize;
continue;
case DT_CONST_ZERO_OFF:
nrp->dofr_data = dtp->dt_zerooffset;
continue;
Expand Down
12 changes: 12 additions & 0 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,14 @@ dt_cg_tramp_prologue_act(dt_pcb_t *pcb, dt_activity_t act)
dt_ident_t *mem = dt_dlib_get_map(dtp, "mem");
dt_ident_t *state = dt_dlib_get_map(dtp, "state");
dt_ident_t *prid = dt_dlib_get_var(pcb->pcb_hdl, "PRID");
dt_ident_t *ro_off = dt_dlib_get_var(dtp, "RODATA_OFF");
uint_t lbl_exit = pcb->pcb_exitlbl;

assert(aggs != NULL);
assert(mem != NULL);
assert(state != NULL);
assert(prid != NULL);
assert(ro_off != NULL);

/*
* On input, %r1 is the BPF context.
Expand Down Expand Up @@ -206,6 +208,16 @@ dt_cg_tramp_prologue_act(dt_pcb_t *pcb, dt_activity_t act)
} while(0)

DT_CG_STORE_MAP_PTR("strtab", DCTX_STRTAB);

/*
* We know that a pointer to the strtab data is in %r0 (because that is
* where the DT_CG_STORE_MAP_PTR() macro left it, and we know that dctx
* is in %r9. So, we can just add RODATA_OFF to %r0, and store that in
* [%r9 + DCTX_RODATA].
*/
emite(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, -1), ro_off);
emit(dlp, BPF_STORE(BPF_DW, BPF_REG_9, DCTX_RODATA, BPF_REG_0));

if (dtp->dt_options[DTRACEOPT_SCRATCHSIZE] > 0)
DT_CG_STORE_MAP_PTR("scratchmem", DCTX_SCRATCHMEM);
if (dt_idhash_datasize(dtp->dt_globals) > 0)
Expand Down
2 changes: 2 additions & 0 deletions libdtrace/dt_dctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ typedef struct dt_dctx {
char *mem; /* General scratch memory */
char *scratchmem; /* Scratch space for alloca, etc */
char *strtab; /* String constant table */
char *rodata; /* Read-only data */
char *agg; /* Aggregation data */
char *gvars; /* Global variables */
char *lvars; /* Local variables */
Expand All @@ -70,6 +71,7 @@ typedef struct dt_dctx {
#define DCTX_MEM offsetof(dt_dctx_t, mem)
#define DCTX_SCRATCHMEM offsetof(dt_dctx_t, scratchmem)
#define DCTX_STRTAB offsetof(dt_dctx_t, strtab)
#define DCTX_RODATA offsetof(dt_dctx_t, rodata)
#define DCTX_AGG offsetof(dt_dctx_t, agg)
#define DCTX_GVARS offsetof(dt_dctx_t, gvars)
#define DCTX_LVARS offsetof(dt_dctx_t, lvars)
Expand Down
2 changes: 2 additions & 0 deletions libdtrace/dt_dlibs.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ static const dt_ident_t dt_bpf_symbols[] = {
DT_BPF_SYMBOL_ID(TASK_COMM, DT_IDENT_SCALAR, DT_CONST_TASK_COMM),
DT_BPF_SYMBOL_ID(MUTEX_OWNER, DT_IDENT_SCALAR, DT_CONST_MUTEX_OWNER),
DT_BPF_SYMBOL_ID(RWLOCK_CNTS, DT_IDENT_SCALAR, DT_CONST_RWLOCK_CNTS),
DT_BPF_SYMBOL_ID(RODATA_OFF, DT_IDENT_SCALAR, DT_CONST_RODATA_OFF),
DT_BPF_SYMBOL_ID(RODATA_SIZE, DT_IDENT_SCALAR, DT_CONST_RODATA_SIZE),
DT_BPF_SYMBOL_ID(ZERO_OFF, DT_IDENT_SCALAR, DT_CONST_ZERO_OFF),

/* End-of-list marker */
Expand Down
10 changes: 8 additions & 2 deletions libdtrace/dt_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C" {
#include <dt_bpf_maps.h>
#include <dt_parser.h>
#include <dt_regset.h>
#include <dt_rodata.h>
#include <dt_strtab.h>
#include <dt_symtab.h>
#include <dt_ident.h>
Expand Down Expand Up @@ -306,14 +307,17 @@ struct dtrace_hdl {
dt_idhash_t *dt_tls; /* hash table of thread-local identifiers */
dt_idhash_t *dt_bpfsyms;/* hash table of BPF identifiers */
dt_strtab_t *dt_ccstab; /* global string table (during compilation) */
dt_rodata_t *dt_rodata; /* global read-only data */
uint_t dt_strlen; /* global string table (runtime) size */
uint_t dt_rooffset; /* read-only data offset */
uint_t dt_rosize; /* read-only data size */
uint_t dt_zerooffset; /* zero region, offset */
uint_t dt_zerosize; /* zero region, size */
uint_t dt_maxreclen; /* largest record size across programs */
uint_t dt_maxdvarsize; /* largest dynamic variable across programs */
uint_t dt_maxtuplesize; /* largest tuple across programs */
uint_t dt_maxlvaralloc; /* largest lvar alloc across pcbs */
uint_t dt_maxaggdsize; /* largest aggregation data sizw */
uint_t dt_zerosize; /* zero region, size */
uint_t dt_zerooffset; /* zero region, offset */
dt_tstring_t *dt_tstrings; /* temporary string slots */
dt_list_t dt_modlist; /* linked list of dt_module_t's */
dt_htab_t *dt_mods; /* hash table of dt_module_t's */
Expand Down Expand Up @@ -725,6 +729,8 @@ extern int dt_version_defined(dt_version_t);

extern int dt_str2kver(const char *, dt_version_t *);

extern uint32_t dt_gen_hval(const char *, uint32_t, size_t);

/*
* Miscellaneous internal libdtrace interfaces. The definitions below are for
* libdtrace routines that do not yet merit their own separate header file.
Expand Down
6 changes: 4 additions & 2 deletions libdtrace/dt_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,11 +888,11 @@ dt_vopen(int version, int flags, int *errp,
DIF_VAR_OTHER_UBASE, DIF_VAR_OTHER_MAX);

dtp->dt_ccstab = dt_strtab_create(BUFSIZ);
dtp->dt_strlen = 0;
dtp->dt_rodata = dt_rodata_create(BUFSIZ);

if (dtp->dt_macros == NULL || dtp->dt_aggs == NULL ||
dtp->dt_globals == NULL || dtp->dt_tls == NULL ||
dtp->dt_ccstab == NULL)
dtp->dt_ccstab == NULL || dtp->dt_rodata == NULL)
return set_open_errno(dtp, errp, EDT_NOMEM);

/*
Expand Down Expand Up @@ -1235,6 +1235,8 @@ dtrace_close(dtrace_hdl_t *dtp)
dt_ident_destroy(idp);
}

if (dtp->dt_rodata != NULL)
dt_rodata_destroy(dtp->dt_rodata);
if (dtp->dt_ccstab != NULL)
dt_strtab_destroy(dtp->dt_ccstab);
if (dtp->dt_macros != NULL)
Expand Down

0 comments on commit 234064d

Please sign in to comment.