[DTrace-devel] [PATCH 3/7] Add rodata support
Eugene Loh
eugene.loh at oracle.com
Thu Jul 27 20:02:22 UTC 2023
This is a kind of long patch, and I do not know what problem it is
trying to solve.
If there is supposed to be read-only data, wouldn't that include strtab
and the zeroes? Why isn't this mechanism being used for them? Or, why
not skip this stuff entirely and just add the inet_ntoa6 table (when it
appears down the road) in the same way that the zeroes were added? As
it is, we simply seem to be adding a lot of complexity (and duplicating
a lot of code from strtab) for no clear purpose.
A big comment block in dt_rodata.h or .c explaining this stuff would be
good.
Meanwhile other comments below.
On 7/27/23 11:29, Kris Van Hees via DTrace-devel wrote:
> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> ---
> libdtrace/Build | 1 +
> libdtrace/dt_bpf.c | 9 +-
> libdtrace/dt_bpf.h | 38 +++---
> libdtrace/dt_cc.c | 6 +
> libdtrace/dt_cg.c | 11 ++
> libdtrace/dt_dctx.h | 2 +
> libdtrace/dt_dlibs.c | 2 +
> libdtrace/dt_impl.h | 10 +-
> libdtrace/dt_open.c | 1 +
> libdtrace/dt_rodata.c | 295 ++++++++++++++++++++++++++++++++++++++++++
> libdtrace/dt_rodata.h | 35 +++++
> libdtrace/dt_subr.c | 22 ++++
> 12 files changed, 411 insertions(+), 21 deletions(-)
> create mode 100644 libdtrace/dt_rodata.c
> create mode 100644 libdtrace/dt_rodata.h
>
> diff --git a/libdtrace/Build b/libdtrace/Build
> index a392c5f3..d1b00933 100644
> --- a/libdtrace/Build
> +++ b/libdtrace/Build
> @@ -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 \
> diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
> index 54086077..b4c880bc 100644
> --- a/libdtrace/dt_bpf.c
> +++ b/libdtrace/dt_bpf.c
> @@ -711,7 +711,9 @@ gmap_create_strtab(dtrace_hdl_t *dtp)
The big block comment describing gmap_create_strtab() should acknowledge
the addition of rodata.
> 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);
>
> /*
> * Ensure the zero-filled memory at the end of the strtab is large
> @@ -730,6 +732,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);
The new comment is helpful. So a few statements earlier, there should
also be a comment about the allocation.
> @@ -745,6 +748,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)
I do not see where this is going. Why are we passing dt_rodata_copy to
a function that is in a file that knows more about dt_rodata_copy than
we do? Is some future alternative use anticipated? If so, how about
allowing someone to pass a NULL function meaning "you know what to do."
I suppose the real issue is we're trying to mimic strtab.
Anyhow, how about adding another comment before the create_gmap() call?
> diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
> index f414e78e..e64ca3c1 100644
> --- a/libdtrace/dt_bpf.h
> +++ b/libdtrace/dt_bpf.h
> @@ -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
> diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
> index 88d7f1fe..2293892c 100644
> --- a/libdtrace/dt_cc.c
> +++ b/libdtrace/dt_cc.c
> @@ -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;
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index bb6cff4a..6a1413f0 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -56,6 +56,7 @@ 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");
While we're here, how about s/pcb->pcb_hdl/dtp/?
> + dt_ident_t *ro_off = dt_dlib_get_var(dtp, "RODATA_OFF");
> uint_t lbl_exit = pcb->pcb_exitlbl;
>
> assert(aggs != NULL);
> @@ -206,6 +207,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)
> diff --git a/libdtrace/dt_dctx.h b/libdtrace/dt_dctx.h
> index 315bdc37..86bfe6f2 100644
> --- a/libdtrace/dt_dctx.h
> +++ b/libdtrace/dt_dctx.h
> @@ -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 */
> @@ -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)
> diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
> index 1005e027..02a24ad2 100644
> --- a/libdtrace/dt_dlibs.c
> +++ b/libdtrace/dt_dlibs.c
> @@ -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 */
> diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
> index 42a7ccaa..adc8d8db 100644
> --- a/libdtrace/dt_impl.h
> +++ b/libdtrace/dt_impl.h
> @@ -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>
> @@ -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 */
> @@ -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.
> diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
> index b6a0b623..a90601b0 100644
> --- a/libdtrace/dt_open.c
> +++ b/libdtrace/dt_open.c
> @@ -888,6 +888,7 @@ 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_rodata = dt_rodata_create(BUFSIZ);
Memory leak? No companion destroy call? (No big deal.)
And do we need to check if NULL was returned?
> dtp->dt_strlen = 0;
>
> if (dtp->dt_macros == NULL || dtp->dt_aggs == NULL ||
> diff --git a/libdtrace/dt_rodata.c b/libdtrace/dt_rodata.c
> new file mode 100644
> index 00000000..cba12d77
> --- /dev/null
> +++ b/libdtrace/dt_rodata.c
> @@ -0,0 +1,295 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
Why 2006? Because we're duplicating code from strtab?
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +#include <sys/types.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <assert.h>
> +
> +#include <dt_rodata.h>
> +#include <dt_string.h>
> +#include <dt_impl.h>
> +
> +typedef struct dt_rohash dt_rohash_t;
> +struct dt_rohash {
> + const char *data; /* pointer to actual data */
> + size_t buf; /* index of data buffer */
> + size_t off; /* offset in bytes of this item */
> + size_t len; /* length in bytes of this item */
> + dt_rohash_t *next; /* next item in hash chain */
> +};
> +
> +struct dt_rodata {
> + dt_rohash_t **hash; /* array of hash buckets */
> + size_t hashsz; /* size of hash bucket array */
> + char **bufs; /* array of buffer pointers */
> + char *ptr; /* pointer to current buffer location */
> + size_t nbufs; /* size of buffer pointer array */
> + size_t bufsz; /* size of individual buffer */
> + size_t count; /* total number of items in rodata */
> + size_t size; /* total size of items in bytes */
> +};
> +
> +static int
> +dt_rodata_grow(dt_rodata_t *dp)
> +{
> + char *ptr, **bufs;
> +
> + ptr = malloc(dp->bufsz);
> + if (ptr == NULL)
> + return -1;
> +
> + bufs = realloc(dp->bufs, (dp->nbufs + 1) * sizeof(char *));
> + if (bufs == NULL) {
> + free(ptr);
> + return -1;
> + }
> +
> + dp->nbufs++;
> + dp->bufs = bufs;
> + dp->ptr = ptr;
> + dp->bufs[dp->nbufs - 1] = dp->ptr;
No big deal, but could "= ptr" here.
> +
> + return 0;
> +}
> +
> +dt_rodata_t *
> +dt_rodata_create(size_t bufsz)
> +{
> + dt_rodata_t *dp = malloc(sizeof(dt_rodata_t));
> + size_t nbuckets = _dtrace_strbuckets;
> +
> + assert(bufsz != 0);
> +
> + if (dp == NULL)
> + return NULL;
> +
> + memset(dp, 0, sizeof(dt_rodata_t));
> + dp->hash = malloc(nbuckets * sizeof(dt_rohash_t *));
> + if (dp->hash == NULL)
> + goto err;
> +
> + memset(dp->hash, 0, nbuckets * sizeof(dt_rohash_t *));
> + dp->hashsz = nbuckets;
> + dp->bufs = NULL;
> + dp->ptr = NULL;
> + dp->nbufs = 0;
> + dp->bufsz = bufsz;
> +
> + if (dt_rodata_grow(dp) == -1)
> + goto err;
> +
> + /* Pre-populate the read-only data with a 0-byte at offset 0. */
Don't hyphenate 0-byte?
> + *dp->ptr++ = 0;
> + dp->size = 1;
> + dp->count = 1;
> +
> + return dp;
> +
> +err:
> + dt_rodata_destroy(dp);
> + return NULL;
> +}
> +
> +void
> +dt_rodata_destroy(dt_rodata_t *dp)
> +{
> + dt_rohash_t *hp, *hq;
> + size_t i;
> +
> + if (dp == NULL)
> + return;
> +
> + for (i = 0; i < dp->hashsz; i++) {
> + for (hp = dp->hash[i]; hp != NULL; hp = hq) {
> + hq = hp->next;
> + free(hp);
> + }
> + }
> +
> + for (i = 0; i < dp->nbufs; i++)
> + free(dp->bufs[i]);
> +
> + if (dp->hash != NULL)
> + free(dp->hash);
> + if (dp->bufs != NULL)
> + free(dp->bufs);
If dp->hash or dp->bufs could be NULL, we should have checked earlier,
before using them.
> +
> + free(dp);
> +}
> +
> +static int
> +dt_rodata_compare(dt_rodata_t *dp, dt_rohash_t *hp, const char *ptr, size_t len)
> +{
> + size_t b = hp->buf;
> + const char *buf = hp->data;
> + size_t resid, n;
> + int rv;
> +
> + while (len != 0) {
> + if (buf == dp->bufs[b] + dp->bufsz)
> + buf = dp->bufs[++b];
> +
> + resid = dp->bufs[b] + dp->bufsz - buf;
> + n = MIN(resid, len);
> +
> + if ((rv = memcmp(buf, ptr, n)) != 0)
> + return rv;
> +
> + buf += n;
> + ptr += n;
> + len -= n;
> + }
> +
> + return 0;
> +}
> +
> +static int
> +dt_rodata_copyin(dt_rodata_t *dp, const char *ptr, size_t len)
> +{
> + char *old_p = dp->ptr;
> + size_t old_n = dp->nbufs;
> + size_t b = dp->nbufs - 1;
> + size_t resid, n;
> +
> + while (len != 0) {
> + if (dp->ptr == dp->bufs[b] + dp->bufsz) {
> + if (dt_rodata_grow(dp) == -1)
> + goto err;
> + b++;
> + }
> +
> + resid = dp->bufs[b] + dp->bufsz - dp->ptr;
> + n = MIN(resid, len);
> + memcpy(dp->ptr, ptr, n);
> +
> + dp->ptr += n;
> + ptr += n;
> + len -= n;
> + }
> +
> + return 0;
> +
> +err:
> + while (dp->nbufs != old_n)
> + free(dp->bufs[--dp->nbufs]);
> +
> + dp->ptr = old_p;
> + return -1;
> +}
> +
> +static ssize_t
> +dt_rodata_xindex(dt_rodata_t *dp, const char *ptr, size_t len, uint32_t h)
How about putting the h%dp->hashsz in here to ensure it's done?
In fact, just move the h=dt_gen_hval() in here rather than passing h in.
> +{
> + dt_rohash_t *hp;
> +
> + for (hp = dp->hash[h]; hp != NULL; hp = hp->next) {
No need for these brackets?
> + if (dt_rodata_compare(dp, hp, ptr, len) == 0)
> + return hp->off;
> + }
> +
> + return -1;
> +}
> +
> +ssize_t
> +dt_rodata_index(dt_rodata_t *dp, const char *ptr, size_t len)
No one uses this?
Or is dt_rodata_insert() supposed to call it?
In which case, xindex can be inlined here.
> +{
> + ssize_t rc;
> + uint32_t h;
> +
> + if (ptr == NULL || ptr[0] == '\0')
> + return 0; /* NULL or a single 0-byte are at offset 0. */
> +
> + h = dt_gen_hval(ptr, len, len) % dp->hashsz;
Why len, len? Why not 0, len?
> + rc = dt_rodata_xindex(dp, ptr, len, h);
> +
> + return rc;
> +}
> +
> +ssize_t
> +dt_rodata_insert(dt_rodata_t *dp, const char *ptr, size_t len)
> +{
> + dt_rohash_t *hp;
> + ssize_t off;
> + uint32_t h;
> +
> + if (ptr == NULL || ptr[0] == '\0')
> + return 0; /* NULL or a single 0-byte are at offset 0. */
> +
> + h = dt_gen_hval(ptr, len, len) % dp->hashsz;
Ditto.
> + off = dt_rodata_xindex(dp, ptr, len, h);
> + if (off != -1)
> + return off;
> +
> + /*
> + * Create a new hash bucket, initialize it, and insert it at the front
> + * of the hash chain for the appropriate bucket.
> + */
> + if ((hp = malloc(sizeof(dt_rohash_t))) == NULL)
> + return -1L;
> +
> + hp->data = dp->ptr;
> + hp->buf = dp->nbufs - 1;
> + hp->off = dp->size;
> + hp->len = len;
> + hp->next = dp->hash[h];
> +
> + /*
> + * Now copy the data into our buffer list, and then update the global
> + * counts of items and bytes. Return the item's byte offset.
> + */
> + if (dt_rodata_copyin(dp, ptr, len) == -1) {
> + free(hp);
> + return -1L;
> + }
> +
> + dp->count++;
> + dp->size += len;
> + dp->hash[h] = hp;
> +
> + return hp->off;
> +}
> +
> +size_t
> +dt_rodata_size(const dt_rodata_t *dp)
> +{
> + return dp->size;
> +}
> +
> +/*
> + * Copy data from the compile-time read-only data into a DIFO-style read-only
> + * storage memory block.
> + */
> +ssize_t
> +dt_rodata_copy(const char *s, size_t n, size_t off, char *buf)
> +{
> + memcpy(buf + off, s, n);
> + return n;
> +}
> +
> +ssize_t
> +dt_rodata_write(const dt_rodata_t *dp, dt_rodata_copy_f *func, void *private)
> +{
> + ssize_t res, total = 0;
> + size_t i;
> + size_t n;
> +
> + for (i = 0; i < dp->nbufs; i++, total += res) {
> + if (i == dp->nbufs - 1)
> + n = dp->ptr - dp->bufs[i];
> + else
> + n = dp->bufsz;
> +
> + if ((res = func(dp->bufs[i], n, total, private)) <= 0)
> + break;
> + }
> +
> + if (total == 0 && dp->size != 0)
> + return -1;
> +
> + return total;
> +}
> diff --git a/libdtrace/dt_rodata.h b/libdtrace/dt_rodata.h
> new file mode 100644
> index 00000000..d995d7ea
> --- /dev/null
> +++ b/libdtrace/dt_rodata.h
> @@ -0,0 +1,35 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
Years?
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +#ifndef _DT_RODATA_H
> +#define _DT_RODATA_H
> +
> +#include <sys/types.h>
> +#include <sys/dtrace_types.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +typedef struct dt_rodata dt_rodata_t;
> +
> +typedef ssize_t dt_rodata_copy_f(const char *, size_t, size_t, void *);
> +
> +extern dt_rodata_t *dt_rodata_create(size_t);
> +extern void dt_rodata_destroy(dt_rodata_t *);
> +extern ssize_t dt_rodata_index(dt_rodata_t *, const char *, size_t);
No one uses _index.
> +extern ssize_t dt_rodata_insert(dt_rodata_t *, const char *, size_t);
> +extern size_t dt_rodata_size(const dt_rodata_t *);
> +extern ssize_t dt_rodata_copy(const char *, size_t, size_t, char *);
Earlier questions about why this is externed.
> +extern ssize_t dt_rodata_write(const dt_rodata_t *, dt_rodata_copy_f *,
> + void *);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _DT_RODATA_H */
> diff --git a/libdtrace/dt_subr.c b/libdtrace/dt_subr.c
> index 300c1a8d..6af2e0c8 100644
> --- a/libdtrace/dt_subr.c
> +++ b/libdtrace/dt_subr.c
> @@ -985,3 +985,25 @@ dt_str2kver(const char *kverstr, dt_version_t *vp)
>
> return 0;
> }
> +
> +/*
> + * Compute a 32-bit hash value for a memory block of given size.
> + */
> +uint32_t dt_gen_hval(const char *p, uint32_t hval, size_t len)
> +{
> + uint32_t g;
> +
> + if (!p || len == 0)
> + return hval;
> +
> + while (len--) {
> + hval = (hval << 4) + *p++;
> + g = hval & 0xf0000000;
> + if (g != 0) {
> + hval ^= (g >> 24);
> + hval ^= g;
> + }
> + }
> +
> + return hval;
> +}
Same algorithm as
dt_spec_buf_hval()
str2hval()
string_hash()
Can anything be consolidated here?
More information about the DTrace-devel
mailing list