[DTrace-devel] [PATCH 07/17] dof_parser: generic parser framework to support multiple parsers
Kris Van Hees
kris.van.hees at oracle.com
Sat Jun 7 06:15:00 UTC 2025
To prepare for non-DOF section based USDT probe definitions, the data
passed from dtprobed to the USDT data parser is more generic. The
dof_helper_t structure is passed first, followed by a block count, and
that number of data blocks, passed as a size followed by the content.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
---
dtprobed/dof_stash.c | 11 +-
dtprobed/dof_stash.h | 7 +-
dtprobed/dtprobed.c | 62 +--
libcommon/Build | 2 +-
libcommon/usdt_parser.c | 227 +++++++++
libcommon/{dof_parser.h => usdt_parser.h} | 70 ++-
libcommon/{dof_parser.c => usdt_parser_dof.c} | 462 ++++++------------
.../{dof_parser_host.c => usdt_parser_host.c} | 46 +-
libdtrace/dt_pid.c | 2 +-
9 files changed, 513 insertions(+), 376 deletions(-)
create mode 100644 libcommon/usdt_parser.c
rename libcommon/{dof_parser.h => usdt_parser.h} (66%)
rename libcommon/{dof_parser.c => usdt_parser_dof.c} (68%)
rename libcommon/{dof_parser_host.c => usdt_parser_host.c} (71%)
diff --git a/dtprobed/dof_stash.c b/dtprobed/dof_stash.c
index 296987ad..6a4ecb86 100644
--- a/dtprobed/dof_stash.c
+++ b/dtprobed/dof_stash.c
@@ -1,6 +1,6 @@
/*
* Oracle Linux DTrace; DOF state storage management.
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, 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.
*
@@ -1568,7 +1568,7 @@ int
reparse_dof(int out, int in,
int (*reparse)(int pid, int out, int in, dev_t dev, ino_t ino,
dev_t unused1, ino_t unused2, dof_helper_t *dh,
- const void *in_buf, size_t in_bufsz, int reparsing),
+ const usdt_data_t *data, int reparsing),
int force)
{
DIR *all_pids_dir;
@@ -1642,6 +1642,7 @@ reparse_dof(int out, int in,
size_t dof_size, dh_size;
void *dof = NULL;
void *dh = NULL;
+ usdt_data_t data;
if (errno != 0) {
fuse_log(FUSE_LOG_ERR, "reparsing DOF: cannot read per-PID DOF mappings for pid %s: %s\n",
@@ -1742,7 +1743,11 @@ reparse_dof(int out, int in,
fuse_log(FUSE_LOG_DEBUG, "Reparsing DOF for PID %s, mapping %s\n",
pid_ent->d_name, mapping_ent->d_name);
- if (reparse(pid, out, in, dev, ino, 0, 0, dh, dof, dof_size, 1) < 0)
+
+ data.buf = dof;
+ data.size = dof_size;
+ data.next = NULL;
+ if (reparse(pid, out, in, dev, ino, 0, 0, dh, &data, 1) < 0)
fuse_log(FUSE_LOG_ERR, "when reparsing DOF, cannot parse DOF for PID %s, mapping %s: ignored\n",
pid_ent->d_name, mapping_ent->d_name);
free(dof);
diff --git a/dtprobed/dof_stash.h b/dtprobed/dof_stash.h
index d44a2bda..1017d2d2 100644
--- a/dtprobed/dof_stash.h
+++ b/dtprobed/dof_stash.h
@@ -1,6 +1,6 @@
/*
* Oracle Linux DTrace; DOF storage for later probe removal.
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, 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.
*/
@@ -12,7 +12,7 @@
#include <stdint.h>
#include <dt_list.h>
-#include "dof_parser.h"
+#include "usdt_parser.h"
typedef struct dof_parsed_list {
dt_list_t list;
@@ -35,8 +35,7 @@ void dof_stash_prune_dead(void);
int reparse_dof(int out, int in,
int (*reparse)(int pid, int out, int in, dev_t dev, ino_t ino,
dev_t unused1, ino_t unused2, dof_helper_t *dh,
- const void *in_buf, size_t in_bufsz,
- int reparsing),
+ const usdt_data_t *data, int reparsing),
int force);
#endif
diff --git a/dtprobed/dtprobed.c b/dtprobed/dtprobed.c
index a9944894..dfdce02c 100644
--- a/dtprobed/dtprobed.c
+++ b/dtprobed/dtprobed.c
@@ -33,6 +33,7 @@
#include <time.h>
#include <unistd.h>
#include <config.h>
+#include <libelf.h>
#include <linux/seccomp.h>
#include <sys/syscall.h>
@@ -62,7 +63,7 @@
#include <dtrace/ioctl.h>
#include <dt_list.h>
-#include "dof_parser.h"
+#include "usdt_parser.h"
#include "dof_stash.h"
#include "libproc.h"
@@ -96,8 +97,8 @@ static const struct cuse_lowlevel_ops dtprobed_clop = {
static int
process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
- dev_t exec_inum, dof_helper_t *dh, const void *in_buf,
- size_t in_bufsz, int reparsing);
+ dev_t exec_inum, dof_helper_t *dh, const usdt_data_t *data,
+ int reparsing);
static void
log_msg(enum fuse_log_level level, const char *fmt, va_list ap)
@@ -310,29 +311,29 @@ parse_dof(int in, int out)
{
int ok;
dof_helper_t *dh;
- dof_hdr_t *dof;
+ usdt_data_t *data;
- dh = dof_copyin_helper(in);
+ dh = usdt_copyin_helper(in);
if (!dh)
return 0;
- dof = dof_copyin_dof(in, out, &ok);
- if (!dof) {
+ data = usdt_copyin_data(in, out, &ok);
+ if (!data) {
free(dh);
return ok;
}
- dof_parse(out, dh, dof);
+ usdt_parse(out, dh, data);
return ok;
}
/*
- * Kick off the sandboxed DOF parser. This is run in a seccomp()ed subprocess,
+ * Kick off the sandboxed USDT parser. This is run in a seccomp()ed subprocess,
* and sends a stream of dof_parsed_t back to this process.
*/
static void
-dof_parser_start(void)
+usdt_parser_start(void)
{
int parser_in[2], parser_out[2];
if ((pipe(parser_in) < 0) ||
@@ -395,10 +396,10 @@ dof_parser_start(void)
}
/*
- * Clean up wreckage if the DOF parser dies: optionally restart it.
+ * Clean up wreckage if the USDT parser dies: optionally restart it.
*/
static void
-dof_parser_tidy(int restart)
+usdt_parser_tidy(int restart)
{
int status = 0;
@@ -413,13 +414,13 @@ dof_parser_tidy(int restart)
close(parser_out_pipe);
if (restart)
- dof_parser_start();
+ usdt_parser_start();
}
static dof_parsed_t *
-dof_read(pid_t pid, int in)
+usdt_read(pid_t pid, int in)
{
- dof_parsed_t *reply = dof_parser_host_read(in, timeout);
+ dof_parsed_t *reply = usdt_parser_host_read(in, timeout);
if (!reply)
return NULL;
@@ -497,6 +498,7 @@ helper_ioctl(fuse_req_t req, int cmd, void *arg,
dev_t dev = 0, exec_dev = 0;
ino_t inum = 0, exec_inum = 0;
int gen;
+ usdt_data_t data;
/*
* We can just ignore FUSE_IOCTL_COMPAT: the 32-bit and 64-bit versions
@@ -687,9 +689,12 @@ chunks_done:
&exec_dev, &exec_inum)) < 0)
goto process_err;
+ data.buf = (void *)buf;
+ data.size = userdata->dof_hdr.dofh_loadsz;
+ data.next = NULL;
if ((gen = process_dof(pid, parser_out_pipe, parser_in_pipe,
dev, inum, exec_dev, exec_inum, &userdata->dh,
- buf, userdata->dof_hdr.dofh_loadsz, 0)) < 0)
+ &data, 0)) < 0)
goto process_err;
if (fuse_reply_ioctl(req, gen, NULL, 0) < 0)
@@ -741,8 +746,8 @@ process_err:
*/
static int
process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
- dev_t exec_inum, dof_helper_t *dh, const void *in_buf,
- size_t in_bufsz, int reparsing)
+ dev_t exec_inum, dof_helper_t *dh, const usdt_data_t *data,
+ int reparsing)
{
dof_parsed_t *provider;
size_t i;
@@ -753,8 +758,7 @@ process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
do {
errmsg = "DOF parser write failed";
- while ((errno = dof_parser_host_write(out, dh,
- (dof_hdr_t *) in_buf)) == EAGAIN);
+ while ((errno = usdt_parser_host_write(out, dh, data)) == EAGAIN);
if (errno != 0)
goto err;
@@ -765,7 +769,7 @@ process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
*/
errmsg = "parsed DOF read failed";
- provider = dof_read(pid, in);
+ provider = usdt_read(pid, in);
if (!provider) {
if (tries++ > 1)
goto err;
@@ -773,7 +777,7 @@ process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
* Tidying reopens the parser in and out pipes: catch
* up with this.
*/
- dof_parser_tidy(1);
+ usdt_parser_tidy(1);
out = parser_out_pipe;
in = parser_in_pipe;
continue;
@@ -791,7 +795,7 @@ process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
provider->provider.name, provider->provider.nprobes);
for (i = 0; i < provider->provider.nprobes; i++) {
- dof_parsed_t *probe = dof_read(pid, in);
+ dof_parsed_t *probe = usdt_read(pid, in);
size_t j;
errmsg = "no probes in this provider, or parse state corrupt";
@@ -803,7 +807,7 @@ process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
j = 0;
do {
- dof_parsed_t *tp = dof_read(pid, in);
+ dof_parsed_t *tp = usdt_read(pid, in);
errmsg = "no tracepoints in a probe, or parse state corrupt";
if (!tp || tp->type == DIT_PROVIDER ||
@@ -822,7 +826,7 @@ process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
}
errmsg = "subsequent provider read failed, or stream not properly terminated";
- provider = dof_read(pid, in);
+ provider = usdt_read(pid, in);
if (!provider)
goto err;
}
@@ -834,7 +838,7 @@ process_dof(pid_t pid, int out, int in, dev_t dev, ino_t inum, dev_t exec_dev,
if (!reparsing)
if ((gen = dof_stash_add(pid, dev, inum, exec_dev, exec_inum, dh,
- in_buf, in_bufsz)) < 0)
+ data->buf, data->size)) < 0)
goto fileio;
if (dof_stash_write_parsed(pid, dev, inum, &accum) < 0) {
@@ -860,7 +864,7 @@ fileio:
proc_err:
dof_stash_free(&accum);
- dof_parser_tidy(1);
+ usdt_parser_tidy(1);
return -1;
}
@@ -1071,7 +1075,7 @@ main(int argc, char *argv[])
testing = 1;
}
- dof_parser_start();
+ usdt_parser_start();
if (dof_stash_init(statedir) < 0)
exit(1);
@@ -1102,7 +1106,7 @@ main(int argc, char *argv[])
ret = loop();
- dof_parser_tidy(0);
+ usdt_parser_tidy(0);
teardown_device();
if (ret == 0)
diff --git a/libcommon/Build b/libcommon/Build
index e8908e7c..f64545ed 100644
--- a/libcommon/Build
+++ b/libcommon/Build
@@ -9,7 +9,7 @@ LIBS += libcommon
libcommon_TARGET = libcommon
libcommon_DIR := $(current-dir)
libcommon_CPPFLAGS := -Ilibcommon -Ilibproc -U_FORTIFY_SOURCE
-libcommon_SOURCES = dof_parser.c dof_parser_host.c dt_list.c
+libcommon_SOURCES = usdt_parser.c usdt_parser_dof.c usdt_parser_host.c dt_list.c
libcommon_NOCFLAGS := -D_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -D_FORTIFY_SOURCE=2 -D_FORTIFY_SOURCE=3 -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=1 -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=2 -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3
libcommon_NOCPPFLAGS := -D_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -D_FORTIFY_SOURCE=2 -D_FORTIFY_SOURCE=3 -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=1 -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=2 -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3
libcommon_LIBSOURCES = libcommon
diff --git a/libcommon/usdt_parser.c b/libcommon/usdt_parser.c
new file mode 100644
index 00000000..f301fd56
--- /dev/null
+++ b/libcommon/usdt_parser.c
@@ -0,0 +1,227 @@
+/*
+ * Oracle Linux DTrace; USDT definitions parser.
+ * Copyright (c) 2010, 2025, 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.
+ */
+
+#include <sys/compiler.h>
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libelf.h>
+#include "usdt_parser.h"
+
+size_t usdt_maxcount = 2;
+size_t usdt_maxsize = 256 * 1024 * 1024;
+
+_dt_printflike_(3, 4)
+void
+usdt_error(int out, int err_no, const char *fmt, ...)
+{
+ dof_parsed_t *parsed;
+ size_t sz;
+ char *msg;
+ va_list ap;
+
+ /*
+ * Not much we can do on OOM of errors other than abort, forcing a
+ * parser restart, which hopefully will have enough memory to report the
+ * error properly.
+ */
+ va_start(ap, fmt);
+ if (vasprintf(&msg, fmt, ap) < 0)
+ abort();
+ va_end(ap);
+
+ sz = offsetof(dof_parsed_t, err.err) + strlen(msg) + 1;
+ parsed = malloc(sz);
+
+ if (!parsed)
+ abort();
+
+ memset(parsed, 0, sz);
+ parsed->size = sz;
+ parsed->type = DIT_ERR;
+ parsed->err.err_no = err_no;
+ strcpy(parsed->err.err, msg);
+
+ usdt_parser_write_one(out, parsed, parsed->size);
+ free(parsed);
+ free(msg);
+}
+
+static char *
+usdt_copyin(int in, char *buf_, size_t sz)
+{
+ char *buf = buf_;
+ size_t i;
+
+ if (!buf) {
+ buf = malloc(sz);
+ if (!buf)
+ abort();
+ }
+
+ memset(buf, 0, sz);
+
+ for (i = 0; i < sz; ) {
+ size_t ret;
+
+ ret = read(in, buf + i, sz - i);
+
+ if (ret < 0) {
+ switch (errno) {
+ case EINTR:
+ continue;
+ default:
+ goto err;
+ }
+ }
+
+ /*
+ * EOF: parsing done, process shutting down or message
+ * truncated. Fail, in any case.
+ */
+ if (ret == 0)
+ goto err;
+
+ i += ret;
+ }
+
+ return buf;
+
+err:
+ if (!buf_)
+ free(buf);
+ return NULL;
+}
+
+dof_helper_t *
+usdt_copyin_helper(int in)
+{
+ return (dof_helper_t *)usdt_copyin(in, NULL, sizeof(dof_helper_t));
+}
+
+static usdt_data_t *
+usdt_copyin_block(int in, int out, int *ok)
+{
+ usdt_data_t *data;
+
+ *ok = 1;
+
+ data = malloc(sizeof(usdt_data_t));
+ if (!data)
+ abort();
+
+ memset(data, 0, sizeof(usdt_data_t));
+
+ /* Get the size of the data block. */
+ if (!usdt_copyin(in, (char *)&data->size, sizeof(data->size)))
+ abort();
+
+ /* Validate the data size. */
+ if (data->size >= usdt_maxsize) {
+ usdt_error(out, E2BIG, "data size %zi exceeds maximum %zi",
+ data->size, usdt_maxsize);
+ return NULL;
+ }
+
+ /* Get the data. */
+ data->buf = (void *)usdt_copyin(in, NULL, data->size);
+ if (!data->buf) {
+ *ok = 0;
+ free(data);
+ return NULL;
+ }
+
+ return data;
+}
+
+static void
+usdt_destroy_data(usdt_data_t *data)
+{
+ while (data) {
+ usdt_data_t *next = data->next;
+
+ free(data->buf);
+ free(data);
+ data = next;
+ }
+}
+
+usdt_data_t *
+usdt_copyin_data(int in, int out, int *ok)
+{
+ usdt_data_t *first = NULL, *last;
+ size_t cnt;
+
+ *ok = 1;
+
+ /* Get the number of data blocks to follow. */
+ if (!usdt_copyin(in, (char *)&cnt, sizeof(cnt)))
+ abort();
+
+ if (cnt >= usdt_maxcount) {
+ usdt_error(out, E2BIG, "block count %zi exceeds maximum %zi",
+ cnt, usdt_maxcount);
+ return NULL;
+ }
+
+ /* Get the data blocks (for each, size followed by content). */
+ while (cnt-- > 0) {
+ usdt_data_t *blk;
+
+ if ((blk = usdt_copyin_block(in, out, ok)) == NULL)
+ goto err;
+
+ if (first == NULL)
+ first = last = blk;
+ else {
+ last->next = blk;
+ last = blk;
+ }
+ }
+
+ return first;
+
+err:
+ usdt_destroy_data(first);
+
+ return NULL;
+}
+
+static void
+usdt_destroy(dof_helper_t *dhp, usdt_data_t *data)
+{
+ free(dhp);
+ usdt_destroy_data(data);
+}
+
+void
+usdt_parse(int out, dof_helper_t *dhp, usdt_data_t *data)
+{
+ dof_parsed_t eof;
+
+ if (usdt_parse_dof(out, dhp, data->buf) != 0)
+ goto err;
+
+ /*
+ * Always emit an EOF, to wake up the caller if nothing else, but also
+ * to notify the caller that there are no more providers to read.
+ */
+ memset(&eof, 0, sizeof(dof_parsed_t));
+
+ eof.size = offsetof(dof_parsed_t, provider.nprobes);
+ eof.type = DIT_EOF;
+ usdt_parser_write_one(out, &eof, eof.size);
+
+err:
+ usdt_destroy(dhp, data);
+}
diff --git a/libcommon/dof_parser.h b/libcommon/usdt_parser.h
similarity index 66%
rename from libcommon/dof_parser.h
rename to libcommon/usdt_parser.h
index de6cea4c..9dd97e28 100644
--- a/libcommon/dof_parser.h
+++ b/libcommon/usdt_parser.h
@@ -1,22 +1,33 @@
/*
- * Oracle Linux DTrace; DOF parser interface with the outside world
- * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Oracle Linux DTrace; USDT definitions parser interface.
+ * Copyright (c) 2022, 2025, 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.
*/
-#ifndef _DOF_PARSER_H
-#define _DOF_PARSER_H
+#ifndef _USDT_PARSER_H
+#define _USDT_PARSER_H
#include <inttypes.h>
#include <stddef.h>
+#include <libelf.h>
#include <dtrace/dof.h>
#include <dtrace/helpers.h>
/*
- * Result of DOF probe parsing. The order of elements in the parsed stream
- * is:
+ * Data transfer unit for the DOF parser.
+ */
+typedef struct usdt_data usdt_data_t;
+struct usdt_data {
+ size_t size;
+ void *buf;
+ usdt_data_t *next;
+};
+
+/*
+ * Result of USDT definitions parsing. The order of elements in the parsed
+ * stream is:
*
* DIT_PROVIDER (at least 1, which contains...)
* DIT_PROBE (at least 1, each of which has...)
@@ -156,55 +167,70 @@ typedef struct dof_parsed {
} dof_parsed_t;
/*
- * Host-side: in dof_parser_host.c. The host is the
- * non-jailed process that talks to the jailed parser.
+ * Host-side: in usdt_parser_host.c.
+ * The host is the non-jailed process that talks to the jailed parser.
*/
/*
- * Write the DOF to the parser pipe OUT.
+ * Write the USDT definitions data to the parser pipe OUT.
*
* Returns 0 on success or a positive errno value on error.
*/
-int dof_parser_host_write(int out, const dof_helper_t *dh, dof_hdr_t *dof);
+int usdt_parser_host_write(int out, const dof_helper_t *dh,
+ const usdt_data_t *data);
/*
- * Read a single DOF structure from a parser pipe. Wait at most TIMEOUT seconds
- * to do so.
+ * Read a single dof_parsed_t structure from a parser pipe. Wait at most
+ * TIMEOUT seconds to do so.
*
* Returns NULL and sets errno on error.
*/
-dof_parsed_t *dof_parser_host_read(int in, int timeout);
+dof_parsed_t *usdt_parser_host_read(int in, int timeout);
-/* Parser-side: in dof_parser.c. */
+/* Parser-side: in usdt_parser.c. */
+
+/*
+ * Report a parser error.
+ */
+void usdt_error(int out, int err_no, const char *fmt, ...);
/*
* Get a dof_helper_t from the input fd.
*
* Returns NULL on failure - no further processing is possible in that case.
*/
-dof_helper_t *dof_copyin_helper(int in);
+dof_helper_t *usdt_copyin_helper(int in);
/*
- * Get a buffer of DOF from the input fd and sanity-check it.
+ * Get a USDT data block from the input fd.
*
* Set OK to zero if no further parsing is possible.
*/
-dof_hdr_t *dof_copyin_dof(int in, int out, int *ok);
+usdt_data_t *usdt_copyin_data(int in, int out, int *ok);
/*
- * Parse probe info out of the passed-in dof_helper_t and dof_hdr_t DOF buffer,
- * and pass it out of OUT in the form of a stream of dof_parser_info_t.
+ * Parse probe info out of the passed-in dof_helper_t and USDT definitions data
+ * block and emit it to OUT in the form of a stream of dof_parser_info_t.
*/
-void dof_parse(int out, dof_helper_t *dhp, dof_hdr_t *dof);
+void usdt_parse(int out, dof_helper_t *dhp, usdt_data_t *data);
+
+/*
+ * Parse probe info out of the passed-in dof_helper_t and DOF section data and
+ * emit it to OUT in the form of a stream of dof_parser_info_t.
+ *
+ * Returns 0 on success or a positive errno value on error.
+ */
+int usdt_parse_dof(int out, dof_helper_t *dhp, dof_hdr_t *dof);
/*
* Shared host and parser-side.
*/
+
/*
* Write something to the parser pipe OUT.
*
* Returns 0 on success or a positive errno value on error.
*/
-int dof_parser_write_one(int out, const void *buf, size_t size);
+int usdt_parser_write_one(int out, const void *buf, size_t size);
-#endif /* _DOF_PARSER_H */
+#endif /* _USDT_PARSER_H */
diff --git a/libcommon/dof_parser.c b/libcommon/usdt_parser_dof.c
similarity index 68%
rename from libcommon/dof_parser.c
rename to libcommon/usdt_parser_dof.c
index ec80cee8..6a7eb377 100644
--- a/libcommon/dof_parser.c
+++ b/libcommon/usdt_parser_dof.c
@@ -1,6 +1,6 @@
/*
- * Oracle Linux DTrace; DOF parser.
- * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Oracle Linux DTrace; USDT definitions parser - DOF.
+ * Copyright (c) 2010, 2025, 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.
*/
@@ -15,12 +15,11 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "dof_parser.h"
+#include <libelf.h>
+#include "usdt_parser.h"
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
-size_t dof_maxsize = 256 * 1024 * 1024;
-
typedef struct dtrace_helper_probedesc {
char *dthpb_prov;
char *dthpb_mod;
@@ -48,144 +47,9 @@ static void dt_dbg_dof(const char *fmt, ...)
#endif
}
-_dt_printflike_(3, 4)
-static void dof_error(int out, int err_no, const char *fmt, ...)
-{
- dof_parsed_t *parsed;
- size_t sz;
- char *msg;
- va_list ap;
-
- /*
- * Not much we can do on OOM of errors other than abort, forcing a
- * parser restart, which hopefully will have enough memory to report the
- * error properly.
- */
- va_start(ap, fmt);
- if (vasprintf(&msg, fmt, ap) < 0)
- abort();
- va_end(ap);
-
- sz = offsetof(dof_parsed_t, err.err) + strlen(msg) + 1;
- parsed = malloc(sz);
-
- if (!parsed)
- abort();
-
- memset(parsed, 0, sz);
- parsed->size = sz;
- parsed->type = DIT_ERR;
- parsed->err.err_no = err_no;
- strcpy(parsed->err.err, msg);
-
- dof_parser_write_one(out, parsed, parsed->size);
- free(parsed);
- free(msg);
-}
-
-static char *
-dof_copyin(int in, char *buf_, size_t sz)
-{
- char *buf = buf_;
- size_t i;
-
- if (!buf) {
- buf = malloc(sz);
- if (!buf)
- abort();
- }
-
- memset(buf, 0, sz);
-
- for (i = 0; i < sz; ) {
- size_t ret;
-
- ret = read(in, buf + i, sz - i);
-
- if (ret < 0) {
- switch (errno) {
- case EINTR:
- continue;
- default:
- goto err;
- }
- }
-
- /*
- * EOF: parsing done, process shutting down or message
- * truncated. Fail, in any case.
- */
- if (ret == 0)
- goto err;
-
- i += ret;
- }
-
- return buf;
-
-err:
- if (!buf_)
- free(buf);
- return NULL;
-}
-
-dof_helper_t *
-dof_copyin_helper(int in)
-{
- return (dof_helper_t *)dof_copyin(in, NULL, sizeof(dof_helper_t));
-}
-
-dof_hdr_t *
-dof_copyin_dof(int in, int out, int *ok)
-{
- dof_hdr_t *dof;
-
- *ok = 1;
-
- /* First get the header, which gives the size of everything else. */
- dof = (dof_hdr_t *)dof_copyin(in, NULL, sizeof(dof_hdr_t));
- if (!dof)
- abort();
-
- /* Validate the DOF load size. */
- if (dof->dofh_loadsz >= dof_maxsize) {
- dof_error(out, E2BIG, "load size %zi exceeds maximum %zi",
- dof->dofh_loadsz, dof_maxsize);
- return NULL;
- }
-
- if (dof->dofh_loadsz < sizeof(dof_hdr_t)) {
- dof_error(out, EINVAL, "invalid load size %zi, "
- "smaller than header size %zi", dof->dofh_loadsz,
- sizeof(dof_hdr_t));
- return NULL;
- }
-
- /* Resize the allocated memory to fit the actual data as well. */
- dof = realloc(dof, dof->dofh_loadsz);
- if (!dof)
- abort();
-
- /* Read the actual data in the allocated buffer. */
- if (!dof_copyin(in, ((char *)dof) + sizeof(dof_hdr_t),
- dof->dofh_loadsz - sizeof(dof_hdr_t))) {
- *ok = 0;
- free(dof);
- return NULL;
- }
-
- return dof;
-}
-
-static void dof_destroy(dof_helper_t *dhp, dof_hdr_t *dof)
-{
- free(dhp);
- free(dof);
-}
-
/*
* Return the dof_sec_t pointer corresponding to a given section index. If the
- * index is not valid, dof_error() is called and NULL is returned. If a type
+ * index is not valid, usdt_error() is called and NULL is returned. If a type
* other than DOF_SECT_NONE is specified, the header is checked against this
* type and NULL is returned if the types do not match.
*/
@@ -199,19 +63,19 @@ static dof_sec_t *dof_sect(int out, dof_hdr_t *dof,
i * dof->dofh_secsize);
if (i >= dof->dofh_secnum) {
- dof_error(out, EINVAL, "referenced section index %u is "
- "invalid, above %u", i, dof->dofh_secnum);
+ usdt_error(out, EINVAL, "referenced section index %u is "
+ "invalid, above %u", i, dof->dofh_secnum);
return NULL;
}
if (!(sec->dofs_flags & DOF_SECF_LOAD)) {
- dof_error(out, EINVAL, "referenced section %u is not loadable", i);
+ usdt_error(out, EINVAL, "referenced section %u is not loadable", i);
return NULL;
}
if (sectype != DOF_SECT_NONE && sectype != sec->dofs_type) {
- dof_error(out, EINVAL, "referenced section %u is the wrong type, "
- "%u, not %u", i, sec->dofs_type, sectype);
+ usdt_error(out, EINVAL, "referenced section %u is the wrong type, "
+ "%u, not %u", i, sec->dofs_type, sectype);
return NULL;
}
@@ -237,10 +101,10 @@ dof_relocate(int out, dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase)
if (sec->dofs_size < sizeof(dof_relohdr_t) ||
sec->dofs_align != sizeof(dof_secidx_t)) {
- dof_error(out, EINVAL, "invalid relocation header: "
- "size %zi (expected %zi); alignment %u (expected %zi)",
- sec->dofs_size, sizeof(dof_relohdr_t),
- sec->dofs_align, sizeof(dof_secidx_t));
+ usdt_error(out, EINVAL, "invalid relocation header: "
+ "size %zi (expected %zi); alignment %u (expected %zi)",
+ sec->dofs_size, sizeof(dof_relohdr_t),
+ sec->dofs_align, sizeof(dof_secidx_t));
return -1;
}
@@ -249,14 +113,14 @@ dof_relocate(int out, dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase)
ts = dof_sect(out, dof, DOF_SECT_NONE, dofr->dofr_tgtsec);
if (ss == NULL || rs == NULL || ts == NULL)
- return -1; /* dof_error() has been called already */
+ return -1; /* usdt_error() has been called already */
if (rs->dofs_entsize < sizeof(dof_relodesc_t) ||
rs->dofs_align != sizeof(uint64_t)) {
- dof_error(out, EINVAL, "invalid relocation section: entsize %i "
- "(expected %zi); alignment %u (expected %zi)",
- rs->dofs_entsize, sizeof(dof_relodesc_t),
- rs->dofs_align, sizeof(uint64_t));
+ usdt_error(out, EINVAL, "invalid relocation section: entsize %i "
+ "(expected %zi); alignment %u (expected %zi)",
+ rs->dofs_entsize, sizeof(dof_relodesc_t),
+ rs->dofs_align, sizeof(uint64_t));
return -1;
}
@@ -273,14 +137,14 @@ dof_relocate(int out, dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase)
if (r->dofr_offset >= ts->dofs_size ||
r->dofr_offset + sizeof(uint64_t) >
ts->dofs_size) {
- dof_error(out, EINVAL, "bad relocation offset: "
- "offset %zi, section size %zi)",
- r->dofr_offset, ts->dofs_size);
+ usdt_error(out, EINVAL, "bad relocation offset: "
+ "offset %zi, section size %zi)",
+ r->dofr_offset, ts->dofs_size);
return -1;
}
if (!IS_ALIGNED(taddr, sizeof(uint64_t))) {
- dof_error(out, EINVAL, "misaligned setx relo");
+ usdt_error(out, EINVAL, "misaligned setx relo");
return -1;
}
@@ -306,8 +170,8 @@ dof_relocate(int out, dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase)
break;
default:
- dof_error(out, EINVAL, "invalid relocation type %i",
- r->dofr_type);
+ usdt_error(out, EINVAL, "invalid relocation type %i",
+ r->dofr_type);
return -1;
}
@@ -331,8 +195,8 @@ dof_slurp(int out, dof_hdr_t *dof, uint64_t ubase)
uint_t i;
if (_dt_unlikely_(dof->dofh_loadsz < sizeof(dof_hdr_t))) {
- dof_error(out, EINVAL, "load size %zi smaller than header %zi",
- dof->dofh_loadsz, sizeof(dof_hdr_t));
+ usdt_error(out, EINVAL, "load size %zi smaller than header %zi",
+ dof->dofh_loadsz, sizeof(dof_hdr_t));
return -1;
}
@@ -347,72 +211,72 @@ dof_slurp(int out, dof_hdr_t *dof, uint64_t ubase)
*/
if (memcmp(&dof->dofh_ident[DOF_ID_MAG0], DOF_MAG_STRING,
DOF_MAG_STRLEN) != 0) {
- dof_error(out, EINVAL, "DOF magic string mismatch: %c%c%c%c "
- "versus %c%c%c%c\n", dof->dofh_ident[DOF_ID_MAG0],
- dof->dofh_ident[DOF_ID_MAG1],
- dof->dofh_ident[DOF_ID_MAG2],
- dof->dofh_ident[DOF_ID_MAG3],
- DOF_MAG_STRING[0],
- DOF_MAG_STRING[1],
- DOF_MAG_STRING[2],
- DOF_MAG_STRING[3]);
+ usdt_error(out, EINVAL, "DOF magic string mismatch: %c%c%c%c "
+ "versus %c%c%c%c\n", dof->dofh_ident[DOF_ID_MAG0],
+ dof->dofh_ident[DOF_ID_MAG1],
+ dof->dofh_ident[DOF_ID_MAG2],
+ dof->dofh_ident[DOF_ID_MAG3],
+ DOF_MAG_STRING[0],
+ DOF_MAG_STRING[1],
+ DOF_MAG_STRING[2],
+ DOF_MAG_STRING[3]);
return -1;
}
if (dof->dofh_ident[DOF_ID_MODEL] != DOF_MODEL_ILP32 &&
dof->dofh_ident[DOF_ID_MODEL] != DOF_MODEL_LP64) {
- dof_error(out, EINVAL, "DOF has invalid data model: %i",
- dof->dofh_ident[DOF_ID_MODEL]);
+ usdt_error(out, EINVAL, "DOF has invalid data model: %i",
+ dof->dofh_ident[DOF_ID_MODEL]);
return -1;
}
if (dof->dofh_ident[DOF_ID_ENCODING] != DOF_ENCODE_NATIVE) {
- dof_error(out, EINVAL, "DOF encoding mismatch: %i, expected %i",
- dof->dofh_ident[DOF_ID_ENCODING], DOF_ENCODE_NATIVE);
+ usdt_error(out, EINVAL, "DOF encoding mismatch: %i, expected %i",
+ dof->dofh_ident[DOF_ID_ENCODING], DOF_ENCODE_NATIVE);
return -1;
}
if (dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_1 &&
dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_2 &&
dof->dofh_ident[DOF_ID_VERSION] != DOF_VERSION_3) {
- dof_error(out, EINVAL, "DOF version mismatch: %i",
- dof->dofh_ident[DOF_ID_VERSION]);
+ usdt_error(out, EINVAL, "DOF version mismatch: %i",
+ dof->dofh_ident[DOF_ID_VERSION]);
return -1;
}
if (dof->dofh_ident[DOF_ID_DIFVERS] != DIF_VERSION_2) {
- dof_error(out, EINVAL, "DOF uses unsupported instruction set %i",
- dof->dofh_ident[DOF_ID_DIFVERS]);
+ usdt_error(out, EINVAL, "DOF uses unsupported instruction set %i",
+ dof->dofh_ident[DOF_ID_DIFVERS]);
return -1;
}
if (dof->dofh_ident[DOF_ID_DIFIREG] > DIF_DIR_NREGS) {
- dof_error(out, EINVAL, "DOF uses too many integer registers: %i > %i",
- dof->dofh_ident[DOF_ID_DIFIREG], DIF_DIR_NREGS);
+ usdt_error(out, EINVAL, "DOF uses too many integer registers: %i > %i",
+ dof->dofh_ident[DOF_ID_DIFIREG], DIF_DIR_NREGS);
return -1;
}
if (dof->dofh_ident[DOF_ID_DIFTREG] > DIF_DTR_NREGS) {
- dof_error(out, EINVAL, "DOF uses too many tuple registers: %i > %i",
- dof->dofh_ident[DOF_ID_DIFTREG], DIF_DTR_NREGS);
+ usdt_error(out, EINVAL, "DOF uses too many tuple registers: %i > %i",
+ dof->dofh_ident[DOF_ID_DIFTREG], DIF_DTR_NREGS);
return -1;
}
for (i = DOF_ID_PAD; i < DOF_ID_SIZE; i++) {
if (dof->dofh_ident[i] != 0) {
- dof_error(out, EINVAL, "DOF has invalid ident byte set: %i = %i",
- i, dof->dofh_ident[i]);
+ usdt_error(out, EINVAL, "DOF has invalid ident byte set: %i = %i",
+ i, dof->dofh_ident[i]);
return -1;
}
}
if (dof->dofh_flags & ~DOF_FL_VALID) {
- dof_error(out, EINVAL, "DOF has invalid flag bits set: %xi", dof->dofh_flags);
+ usdt_error(out, EINVAL, "DOF has invalid flag bits set: %xi", dof->dofh_flags);
return -1;
}
if (dof->dofh_secsize == 0) {
- dof_error(out, EINVAL, "zero section header size");
+ usdt_error(out, EINVAL, "zero section header size");
return -1;
}
@@ -425,18 +289,18 @@ dof_slurp(int out, dof_hdr_t *dof, uint64_t ubase)
if (dof->dofh_secoff > len || seclen > len ||
dof->dofh_secoff + seclen > len) {
- dof_error(out, EINVAL, "truncated section headers: %zi, %zi, %zi",
- dof->dofh_secoff, len, seclen);
+ usdt_error(out, EINVAL, "truncated section headers: %zi, %zi, %zi",
+ dof->dofh_secoff, len, seclen);
return -1;
}
if (!IS_ALIGNED(dof->dofh_secoff, sizeof(uint64_t))) {
- dof_error(out, EINVAL, "misaligned section headers");
+ usdt_error(out, EINVAL, "misaligned section headers");
return -1;
}
if (!IS_ALIGNED(dof->dofh_secsize, sizeof(uint64_t))) {
- dof_error(out, EINVAL, "misaligned section size");
+ usdt_error(out, EINVAL, "misaligned section size");
return -1;
}
@@ -454,8 +318,8 @@ dof_slurp(int out, dof_hdr_t *dof, uint64_t ubase)
if (DOF_SEC_ISLOADABLE(sec->dofs_type) &&
!(sec->dofs_flags & DOF_SECF_LOAD)) {
- dof_error(out, EINVAL, "loadable section %i with load flag unset",
- i);
+ usdt_error(out, EINVAL, "loadable section %i with load flag unset",
+ i);
return -1;
}
@@ -466,30 +330,30 @@ dof_slurp(int out, dof_hdr_t *dof, uint64_t ubase)
continue;
if (sec->dofs_align & (sec->dofs_align - 1)) {
- dof_error(out, EINVAL, "bad section %i alignment %x", i,
- sec->dofs_align);
+ usdt_error(out, EINVAL, "bad section %i alignment %x",
+ i, sec->dofs_align);
return -1;
}
if (sec->dofs_offset & (sec->dofs_align - 1)) {
- dof_error(out, EINVAL, "misaligned section %i: %lx, "
- "stated alignment %xi", i, sec->dofs_offset,
- sec->dofs_align);
+ usdt_error(out, EINVAL, "misaligned section %i: %lx, "
+ "stated alignment %xi", i, sec->dofs_offset,
+ sec->dofs_align);
return -1;
}
if (sec->dofs_offset > len || sec->dofs_size > len ||
sec->dofs_offset + sec->dofs_size > len) {
- dof_error(out, EINVAL, "corrupt section %i header: "
- "offset %lx, size %lx, len %lx", i,
- sec->dofs_offset, sec->dofs_size, len);
+ usdt_error(out, EINVAL, "corrupt section %i header: "
+ "offset %lx, size %lx, len %lx", i,
+ sec->dofs_offset, sec->dofs_size, len);
return -1;
}
if (sec->dofs_type == DOF_SECT_STRTAB && *((char *)daddr +
sec->dofs_offset + sec->dofs_size - 1) != '\0') {
- dof_error(out, EINVAL, "section %i: non-0-terminated "
- "string table", i);
+ usdt_error(out, EINVAL, "section %i: non-0-terminated "
+ "string table", i);
return -1;
}
}
@@ -540,13 +404,13 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
uint_t nprobes, j, k;
if (_dt_unlikely_(sec->dofs_type != DOF_SECT_PROVIDER)) {
- dof_error(out, EINVAL, "DOF is not provider DOF: %i", sec->dofs_type);
+ usdt_error(out, EINVAL, "DOF is not provider DOF: %i", sec->dofs_type);
return -1;
}
if (sec->dofs_offset & (sizeof(uint_t) - 1)) {
- dof_error(out, EINVAL, "misaligned section offset: %lx",
- sec->dofs_offset);
+ usdt_error(out, EINVAL, "misaligned section offset: %lx",
+ sec->dofs_offset);
return -1;
}
@@ -558,8 +422,8 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
((dof->dofh_ident[DOF_ID_VERSION] == DOF_VERSION_1)
? offsetof(dof_provider_t, dofpv_prenoffs)
: sizeof(dof_provider_t))) {
- dof_error(out, EINVAL, "provider section too small: %lx",
- sec->dofs_size);
+ usdt_error(out, EINVAL, "provider section too small: %lx",
+ sec->dofs_size);
return -1;
}
@@ -587,45 +451,45 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
strtab = (char *)(uintptr_t)(daddr + str_sec->dofs_offset);
if (prov->dofpv_name >= str_sec->dofs_size) {
- dof_error(out, EINVAL, "invalid provider name offset: %u > %zi",
- prov->dofpv_name, str_sec->dofs_size);
+ usdt_error(out, EINVAL, "invalid provider name offset: %u > %zi",
+ prov->dofpv_name, str_sec->dofs_size);
return -1;
}
if (strlen(strtab + prov->dofpv_name) >= DTRACE_PROVNAMELEN) {
- dof_error(out, EINVAL, "provider name too long: %s",
- strtab + prov->dofpv_name);
+ usdt_error(out, EINVAL, "provider name too long: %s",
+ strtab + prov->dofpv_name);
return -1;
}
if (prb_sec->dofs_entsize == 0 ||
prb_sec->dofs_entsize > prb_sec->dofs_size) {
- dof_error(out, EINVAL, "invalid entry size %x, max %lx",
- prb_sec->dofs_entsize, prb_sec->dofs_size);
+ usdt_error(out, EINVAL, "invalid entry size %x, max %lx",
+ prb_sec->dofs_entsize, prb_sec->dofs_size);
return -1;
}
if (prb_sec->dofs_entsize & (sizeof(uintptr_t) - 1)) {
- dof_error(out, EINVAL, "misaligned entry size %x",
- prb_sec->dofs_entsize);
+ usdt_error(out, EINVAL, "misaligned entry size %x",
+ prb_sec->dofs_entsize);
return -1;
}
if (off_sec->dofs_entsize != sizeof(uint32_t)) {
- dof_error(out, EINVAL, "invalid entry size %x",
- off_sec->dofs_entsize);
+ usdt_error(out, EINVAL, "invalid entry size %x",
+ off_sec->dofs_entsize);
return -1;
}
if (off_sec->dofs_offset & (sizeof(uint32_t) - 1)) {
- dof_error(out, EINVAL, "misaligned section offset %lx",
- off_sec->dofs_offset);
+ usdt_error(out, EINVAL, "misaligned section offset %lx",
+ off_sec->dofs_offset);
return -1;
}
if (arg_sec->dofs_entsize != sizeof(uint8_t)) {
- dof_error(out, EINVAL, "invalid entry size %x",
- arg_sec->dofs_entsize);
+ usdt_error(out, EINVAL, "invalid entry size %x",
+ arg_sec->dofs_entsize);
return -1;
}
@@ -644,28 +508,28 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
j * prb_sec->dofs_entsize);
if (prb->dofpr_func >= str_sec->dofs_size) {
- dof_error(out, EINVAL, "invalid function name: "
- "strtab offset %x, max %lx", prb->dofpr_func,
- str_sec->dofs_size);
+ usdt_error(out, EINVAL, "invalid function name: "
+ "strtab offset %x, max %lx", prb->dofpr_func,
+ str_sec->dofs_size);
return -1;
}
if (strlen(strtab + prb->dofpr_func) >= DTRACE_FUNCNAMELEN) {
- dof_error(out, EINVAL, "function name %s too long",
- strtab + prb->dofpr_func);
+ usdt_error(out, EINVAL, "function name %s too long",
+ strtab + prb->dofpr_func);
return -1;
}
if (prb->dofpr_name >= str_sec->dofs_size) {
- dof_error(out, EINVAL, "invalid probe name: "
- "strtab offset %x, max %lx", prb->dofpr_name,
- str_sec->dofs_size);
+ usdt_error(out, EINVAL, "invalid probe name: "
+ "strtab offset %x, max %lx", prb->dofpr_name,
+ str_sec->dofs_size);
return -1;
}
if (strlen(strtab + prb->dofpr_name) >= DTRACE_NAMELEN) {
- dof_error(out, EINVAL, "probe name %s too long",
- strtab + prb->dofpr_name);
+ usdt_error(out, EINVAL, "probe name %s too long",
+ strtab + prb->dofpr_name);
return -1;
}
@@ -676,10 +540,10 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
if (prb->dofpr_offidx + prb->dofpr_noffs < prb->dofpr_offidx ||
(prb->dofpr_offidx + prb->dofpr_noffs) *
off_sec->dofs_entsize > off_sec->dofs_size) {
- dof_error(out, EINVAL, "invalid probe offset %x "
- "(offset count %x, section entsize %x, size %lx)",
- prb->dofpr_offidx, prb->dofpr_noffs,
- off_sec->dofs_entsize, off_sec->dofs_size);
+ usdt_error(out, EINVAL, "invalid probe offset %x "
+ "(offset count %x, section entsize %x, size %lx)",
+ prb->dofpr_offidx, prb->dofpr_noffs,
+ off_sec->dofs_entsize, off_sec->dofs_size);
return -1;
}
@@ -693,8 +557,8 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
if (enoff_sec == NULL) {
if (prb->dofpr_enoffidx != 0 ||
prb->dofpr_nenoffs != 0) {
- dof_error(out, EINVAL,
- "is-enabled offsets with null section");
+ usdt_error(out, EINVAL,
+ "is-enabled offsets with null section");
return -1;
}
} else if (prb->dofpr_enoffidx + prb->dofpr_nenoffs <
@@ -702,29 +566,29 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
(prb->dofpr_enoffidx + prb->dofpr_nenoffs) *
enoff_sec->dofs_entsize >
enoff_sec->dofs_size) {
- dof_error(out, EINVAL, "invalid is-enabled offset %x "
- "(offset count %x, section entsize %x, size %lx)",
- prb->dofpr_enoffidx, prb->dofpr_nenoffs,
- enoff_sec->dofs_entsize, enoff_sec->dofs_size);
+ usdt_error(out, EINVAL, "invalid is-enabled offset %x "
+ "(offset count %x, section entsize %x, size %lx)",
+ prb->dofpr_enoffidx, prb->dofpr_nenoffs,
+ enoff_sec->dofs_entsize, enoff_sec->dofs_size);
return -1;
}
if (prb->dofpr_noffs + prb->dofpr_nenoffs == 0) {
- dof_error(out, EINVAL, "zero probe and is-enabled offsets");
+ usdt_error(out, EINVAL, "zero probe and is-enabled offsets");
return -1;
}
} else if (prb->dofpr_noffs == 0) {
- dof_error(out, EINVAL, "zero probe offsets");
+ usdt_error(out, EINVAL, "zero probe offsets");
return -1;
}
if (prb->dofpr_argidx + prb->dofpr_xargc < prb->dofpr_argidx ||
(prb->dofpr_argidx + prb->dofpr_xargc) *
arg_sec->dofs_entsize > arg_sec->dofs_size) {
- dof_error(out, EINVAL, "invalid args, idx %x "
- "(offset count %x, section entsize %x, size %lx)",
- prb->dofpr_argidx, prb->dofpr_xargc,
- arg_sec->dofs_entsize, arg_sec->dofs_size);
+ usdt_error(out, EINVAL, "invalid args, idx %x "
+ "(offset count %x, section entsize %x, size %lx)",
+ prb->dofpr_argidx, prb->dofpr_xargc,
+ arg_sec->dofs_entsize, arg_sec->dofs_size);
return -1;
}
@@ -732,15 +596,15 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
typestr = strtab + prb->dofpr_nargv;
for (k = 0; k < prb->dofpr_nargc; k++) {
if (typeidx >= str_sec->dofs_size) {
- dof_error(out, EINVAL, "bad native argument type "
- "for arg %i: %x", k, typeidx);
+ usdt_error(out, EINVAL, "bad native argument type "
+ "for arg %i: %x", k, typeidx);
return -1;
}
typesz = strlen(typestr) + 1;
if (typesz > DTRACE_ARGTYPELEN) {
- dof_error(out, EINVAL, "native argument type for arg %i "
- "too long: %s", k, typestr);
+ usdt_error(out, EINVAL, "native argument type for arg %i "
+ "too long: %s", k, typestr);
return -1;
}
@@ -752,23 +616,23 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
typestr = strtab + prb->dofpr_xargv;
for (k = 0; k < prb->dofpr_xargc; k++) {
if (arg[prb->dofpr_argidx + k] > prb->dofpr_nargc) {
- dof_error(out, EINVAL, "bad native argument index "
- "for arg %i: %i (max %i)", k,
- arg[prb->dofpr_argidx + k],
- prb->dofpr_nargc);
+ usdt_error(out, EINVAL, "bad native argument index "
+ "for arg %i: %i (max %i)", k,
+ arg[prb->dofpr_argidx + k],
+ prb->dofpr_nargc);
return -1;
}
if (typeidx >= str_sec->dofs_size) {
- dof_error(out, EINVAL, "bad translated argument type "
- "for arg %i: %x", k, typeidx);
+ usdt_error(out, EINVAL, "bad translated argument type "
+ "for arg %i: %x", k, typeidx);
return -1;
}
typesz = strlen(typestr) + 1;
if (typesz > DTRACE_ARGTYPELEN) {
- dof_error(out, EINVAL, "translated argument type for arg %i "
- "too long: %s", k, typestr);
+ usdt_error(out, EINVAL, "translated argument type for arg %i "
+ "too long: %s", k, typestr);
return -1;
}
@@ -798,7 +662,7 @@ emit_tp(int out, uint64_t base, uint64_t offs, int is_enabled)
tp.type = DIT_TRACEPOINT;
tp.tracepoint.addr = base + offs;
tp.tracepoint.is_enabled = is_enabled;
- dof_parser_write_one(out, &tp, tp.size);
+ usdt_parser_write_one(out, &tp, tp.size);
dt_dbg_dof(" Tracepoint at 0x%lx (0x%llx + 0x%x)%s\n",
base + offs, base, offs, is_enabled ? " (is_enabled)" : "");
@@ -823,9 +687,9 @@ validate_probe(int out, dtrace_helper_probedesc_t *dhpb)
for (i = 1; i < dhpb->dthpb_noffs; i++) {
if (dhpb->dthpb_base + dhpb->dthpb_offs[i] <=
dhpb->dthpb_base + dhpb->dthpb_offs[i - 1]) {
- dof_error(out, EINVAL, "non-unique USDT offsets at %i: %li <= %li",
- i, dhpb->dthpb_base + dhpb->dthpb_offs[i],
- dhpb->dthpb_base + dhpb->dthpb_offs[i - 1]);
+ usdt_error(out, EINVAL, "non-unique USDT offsets at %i: %li <= %li",
+ i, dhpb->dthpb_base + dhpb->dthpb_offs[i],
+ dhpb->dthpb_base + dhpb->dthpb_offs[i - 1]);
return -1;
}
}
@@ -835,16 +699,16 @@ validate_probe(int out, dtrace_helper_probedesc_t *dhpb)
for (i = 1; i < dhpb->dthpb_nenoffs; i++) {
if (dhpb->dthpb_base + dhpb->dthpb_enoffs[i] <=
dhpb->dthpb_base + dhpb->dthpb_enoffs[i - 1]) {
- dof_error(out, EINVAL, "non-unique is-enabled USDT offsets "
- "at %i: %li <= %li", i,
- dhpb->dthpb_base + dhpb->dthpb_enoffs[i],
- dhpb->dthpb_base + dhpb->dthpb_enoffs[i - 1]);
+ usdt_error(out, EINVAL, "non-unique is-enabled USDT offsets "
+ "at %i: %li <= %li", i,
+ dhpb->dthpb_base + dhpb->dthpb_enoffs[i],
+ dhpb->dthpb_base + dhpb->dthpb_enoffs[i - 1]);
return -1;
}
}
if (dhpb->dthpb_noffs == 0 && dhpb->dthpb_nenoffs == 0) {
- dof_error(out, EINVAL, "USDT probe with zero tracepoints");
+ usdt_error(out, EINVAL, "USDT probe with zero tracepoints");
return -1;
}
return 0;
@@ -905,7 +769,7 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
ptr = stpcpy(ptr, dhpb->dthpb_func);
ptr++;
strcpy(ptr, dhpb->dthpb_name);
- dof_parser_write_one(out, msg, msg_size);
+ usdt_parser_write_one(out, msg, msg_size);
free(msg);
@@ -932,7 +796,7 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
msg->size = msg_size;
msg->type = DIT_ARGS_NATIVE;
memcpy(msg->nargs.args, dhpb->dthpb_ntypes, nargs_size);
- dof_parser_write_one(out, msg, msg_size);
+ usdt_parser_write_one(out, msg, msg_size);
free(msg);
@@ -955,7 +819,7 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
msg->size = msg_size;
msg->type = DIT_ARGS_XLAT;
memcpy(msg->xargs.args, dhpb->dthpb_xtypes, xargs_size);
- dof_parser_write_one(out, msg, msg_size);
+ usdt_parser_write_one(out, msg, msg_size);
free(msg);
@@ -974,7 +838,7 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
msg->size = msg_size;
msg->type = DIT_ARGS_MAP;
memcpy(msg->argmap.argmap, dhpb->dthpb_args, map_size);
- dof_parser_write_one(out, msg, msg_size);
+ usdt_parser_write_one(out, msg, msg_size);
free(msg);
}
}
@@ -996,8 +860,8 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
return;
oom:
- dof_error(out, ENOMEM, "Out of memory allocating %zi bytes for probe",
- msg_size);
+ usdt_error(out, ENOMEM, "Out of memory allocating %zi bytes for probe",
+ msg_size);
}
static void
@@ -1062,7 +926,7 @@ emit_provider(int out, dof_helper_t *dhp,
provider_msg = malloc(provider_msg_size);
if (!provider_msg) {
- dof_error(out, ENOMEM, "Out of memory allocating probe");
+ usdt_error(out, ENOMEM, "Out of memory allocating probe");
return;
}
memset(provider_msg, 0, provider_msg_size);
@@ -1071,7 +935,7 @@ emit_provider(int out, dof_helper_t *dhp,
provider_msg->type = DIT_PROVIDER;
provider_msg->provider.nprobes = prb_sec->dofs_size / prb_sec->dofs_entsize;
strcpy(provider_msg->provider.name, dhpb.dthpb_prov);
- dof_parser_write_one(out, provider_msg, provider_msg_size);
+ usdt_parser_write_one(out, provider_msg, provider_msg_size);
/*
* Pass back info on the probes and their associated tracepoints.
@@ -1110,21 +974,24 @@ emit_provider(int out, dof_helper_t *dhp,
free(provider_msg);
}
-void
-dof_parse(int out, dof_helper_t *dhp, dof_hdr_t *dof)
+int
+usdt_parse_dof(int out, dof_helper_t *dhp, dof_hdr_t *dof)
{
- int i, rv;
- uintptr_t daddr = (uintptr_t)dof;
- dof_parsed_t eof;
+ int i;
+ uintptr_t daddr = (uintptr_t)dof;
+
+ if (dof->dofh_loadsz < sizeof(dof_hdr_t)) {
+ usdt_error(out, EINVAL, "invalid load size %zi, "
+ "smaller than header size %zi",
+ dof->dofh_loadsz, sizeof(dof_hdr_t));
+ return -1;
+ }
dt_dbg_dof("DOF 0x%p from helper {'%s', %p, %p}...\n",
dof, dhp ? dhp->dofhp_mod : "<none>", dhp, dof);
- rv = dof_slurp(out, dof, dhp->dofhp_addr);
- if (rv != 0) {
- dof_destroy(dhp, dof);
- return;
- }
+ if (dof_slurp(out, dof, dhp->dofhp_addr) != 0)
+ return -1;
/*
* Look for providers, validate their descriptions, and parse them.
@@ -1142,23 +1009,12 @@ dof_parse(int out, dof_helper_t *dhp, dof_hdr_t *dof)
if (sec->dofs_type != DOF_SECT_PROVIDER)
continue;
- if (validate_provider(out, dof, sec) != 0) {
- dof_destroy(dhp, dof);
- return;
- }
+ if (validate_provider(out, dof, sec) != 0)
+ return -1;
+
emit_provider(out, dhp, dof, sec);
}
}
- /*
- * Always emit an EOF, to wake up the caller if nothing else, but also
- * to notify the caller that there are no more providers to read.
- */
- memset(&eof, 0, sizeof(dof_parsed_t));
-
- eof.size = offsetof(dof_parsed_t, provider.nprobes);
- eof.type = DIT_EOF;
- dof_parser_write_one(out, &eof, eof.size);
-
- dof_destroy(dhp, dof);
+ return 0;
}
diff --git a/libcommon/dof_parser_host.c b/libcommon/usdt_parser_host.c
similarity index 71%
rename from libcommon/dof_parser_host.c
rename to libcommon/usdt_parser_host.c
index 5a7546af..2e824635 100644
--- a/libcommon/dof_parser_host.c
+++ b/libcommon/usdt_parser_host.c
@@ -1,6 +1,6 @@
/*
- * Oracle Linux DTrace; DOF-consumption and USDT-probe-creation daemon.
- * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Oracle Linux DTrace; Host-parser communication implementation.
+ * Copyright (c) 2022, 2025, 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.
*/
@@ -12,8 +12,8 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
-
-#include "dof_parser.h"
+#include <libelf.h>
+#include "usdt_parser.h"
/*
* Write BUF to the parser pipe OUT.
@@ -21,7 +21,7 @@
* Returns 0 on success or a positive errno value on error.
*/
int
-dof_parser_write_one(int out, const void *buf_, size_t size)
+usdt_parser_write_one(int out, const void *buf_, size_t size)
{
size_t i;
char *buf = (char *) buf_;
@@ -51,26 +51,46 @@ dof_parser_write_one(int out, const void *buf_, size_t size)
* Returns 0 on success or a positive errno value on error.
*/
int
-dof_parser_host_write(int out, const dof_helper_t *dh, dof_hdr_t *dof)
+usdt_parser_host_write(int out, const dof_helper_t *dh, const usdt_data_t *data)
{
int err;
+ size_t cnt = 0;
+ const usdt_data_t *blk;
+
+ /* Write dof_helper_t structure. */
+ if ((err = usdt_parser_write_one(out, (const char *)dh,
+ sizeof(*dh))) < 0)
+ return err;
+
+ /* Count and write nunmber of blocks that follow. */
+ for (blk = data; blk != NULL; blk = blk->next)
+ cnt++;
- if ((err = dof_parser_write_one(out, (const char *)dh,
- sizeof(dof_helper_t))) < 0)
+ if ((err = usdt_parser_write_one(out, (const char *)&cnt,
+ sizeof(cnt))) < 0)
return err;
- return dof_parser_write_one(out, (const char *)dof,
- dof->dofh_loadsz);
+ /* Write the blocks (for each, size followed by data). */
+ for (blk = data; blk != NULL; blk = blk->next) {
+ if ((err = usdt_parser_write_one(out, (const char *)&blk->size,
+ sizeof(blk->size))) < 0)
+ return err;
+ if ((err = usdt_parser_write_one(out, (const char *)blk->buf,
+ blk->size)) < 0)
+ return err;
+ }
+
+ return 0;
}
/*
- * Read a single DOF structure from a parser pipe. Wait at most TIMEOUT seconds
- * to do so.
+ * Read a single dof_parsed_t structure from a parser pipe. Wait at most
+ * TIMEOUT seconds to do so.
*
* Returns NULL and sets errno on error.
*/
dof_parsed_t *
-dof_parser_host_read(int in, int timeout)
+usdt_parser_host_read(int in, int timeout)
{
size_t i, sz;
dof_parsed_t *reply;
diff --git a/libdtrace/dt_pid.c b/libdtrace/dt_pid.c
index 4aa94d81..9b1a2278 100644
--- a/libdtrace/dt_pid.c
+++ b/libdtrace/dt_pid.c
@@ -30,7 +30,7 @@
#endif
#include <port.h>
-#include <dof_parser.h>
+#include <usdt_parser.h>
#include <dt_impl.h>
#include <dt_program.h>
--
2.45.2
More information about the DTrace-devel
mailing list