Linux DTrace development list
 help / color / mirror / Atom feed
From: Kris Van Hees <kris.van.hees@oracle.com>
To: dtrace@lists.linux.dev, dtrace-devel@oss.oracle.com
Subject: [PATCH 1/4] ctf: restore support for raw CTF archives
Date: Mon, 09 Nov 2026 20:09:12 +0000	[thread overview]
Message-ID: <8ae83c7a93f20b725d46fd3553a21c1b@oracle.com> (raw)

dt_ctfa_open() replaced ctf_arc_open() for GNU libctf builds but required
the input to be an ELF file with a .ctf section. Raw CTF archives were
rejected before reaching libctf.

Use a temporary libelf context to distinguish ELF inputs from raw data.
Extract .ctf for ELF files and pass the whole buffer for raw archives,
retaining the backing data until the archive is closed. This also avoids
borrowing the registered vmlinux module as an ELF loader context.

Extend the shared CTF test to load the same archive in raw and ELF form,
with both shared_ctf and vmlinux initiating dictionary loading across
repeated module updates.

Fixes: f49e2063d6c1 ("ctf: introduce dt_ctfa_open to support ctf-nobfd")
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
---
 libdtrace/dt_module.c      | 57 ++++++++++++++------------------------
 test/triggers/shared-ctf.c | 13 +++++++--
 2 files changed, 31 insertions(+), 39 deletions(-)

diff --git a/libdtrace/dt_module.c b/libdtrace/dt_module.c
index 06bd55d9..887a4b4e 100644
--- a/libdtrace/dt_module.c
+++ b/libdtrace/dt_module.c
@@ -720,44 +720,27 @@ dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
 
 #ifdef HAVE_LIBCTF
 /*
- * libctf-nobfd cannot use the BFD-backed ctf_arc_open() helper, so extract
- * the .ctf section ourselves and open that with ctf_arc_bufopen().
+ * libctf-nobfd cannot use the BFD-backed ctf_arc_open() helper.  Open raw
+ * archives directly, or extract the .ctf section from ELF files, and pass
+ * the data to ctf_arc_bufopen().
  */
 static ctf_archive_t *
 dt_ctfa_open(dtrace_hdl_t *dtp, const char *ctfa_name)
 {
 	ctf_archive_t	*ctfa = NULL;
 	ctf_sect_t	ctsp = { 0 };
-	dt_module_t	*dmp;
-	char		dm_file[PATH_MAX];
-	const dt_modops_t	*dm_ops;
-	Elf		*dm_elf;
+	dt_module_t	mod = { 0 };
 	void		*ctfa_data = NULL;
+	int		fd;
 
-	dmp = dtp->dt_exec;
-	if (dmp == NULL || strcmp(dmp->dm_name, "vmlinux") != 0)
-		dmp = dt_module_lookup_by_name(dtp, "vmlinux");
-	if (dmp == NULL) {
-		dtp->dt_ctferr = ECTF_INTERNAL;
+	if ((fd = open(ctfa_name, O_RDONLY)) == -1) {
+		dtp->dt_ctferr = errno;
 		return NULL;
 	}
 
-	/*
-	 * Borrow the registered vmlinux module as the ELF loader context, but
-	 * leave its persistent module state exactly as we found it.
-	 */
-	memcpy(dm_file, dmp->dm_file, sizeof(dm_file));
-	dm_ops = dmp->dm_ops;
-	dm_elf = dmp->dm_elf;
-
-	if (strlcpy(dmp->dm_file, ctfa_name, sizeof(dmp->dm_file)) >=
-	    sizeof(dmp->dm_file)) {
-		dtp->dt_ctferr = ENAMETOOLONG;
-		goto out;
-	}
-
 	errno = 0;
-	if (dt_module_init_elf_impl(dtp, dmp, 0) != 0) {
+	mod.dm_elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+	if (mod.dm_elf == NULL) {
 		dtp->dt_ctferr = errno != 0 ? errno : ECTF_FMT;
 		goto out;
 	}
@@ -765,9 +748,15 @@ dt_ctfa_open(dtrace_hdl_t *dtp, const char *ctfa_name)
 	ctsp.cts_name = ".ctf";
 	ctsp.cts_entsize = 0;
 
-	if (dt_module_load_sect(dtp, dmp, &ctsp) == -1) {
-		dtp->dt_ctferr = ECTF_FMT;
-		goto out;
+	if (elf_kind(mod.dm_elf) == ELF_K_ELF) {
+		strcpy(mod.dm_name, "CTF archive");
+		if (dt_module_load_sect(dtp, &mod, &ctsp) == -1) {
+			dtp->dt_ctferr = ECTF_FMT;
+			goto out;
+		}
+	} else {
+		/* libctf validates the raw archive or dictionary header. */
+		ctsp.cts_data = elf_rawfile(mod.dm_elf, &ctsp.cts_size);
 	}
 
 	if (ctsp.cts_data == NULL || ctsp.cts_size == 0) {
@@ -792,13 +781,9 @@ dt_ctfa_open(dtrace_hdl_t *dtp, const char *ctfa_name)
 
 out:
 	free(ctfa_data);
-	if (dmp->dm_elf != dm_elf) {
-		if (dmp->dm_elf != NULL)
-			elf_end(dmp->dm_elf);
-		dmp->dm_elf = dm_elf;
-	}
-	dmp->dm_ops = dm_ops;
-	memcpy(dmp->dm_file, dm_file, sizeof(dmp->dm_file));
+	if (mod.dm_elf != NULL)
+		elf_end(mod.dm_elf);
+	close(fd);
 	return ctfa;
 }
 #endif
diff --git a/test/triggers/shared-ctf.c b/test/triggers/shared-ctf.c
index 5772429a..8e20fb7b 100644
--- a/test/triggers/shared-ctf.c
+++ b/test/triggers/shared-ctf.c
@@ -61,7 +61,7 @@ write_elf(const char *path, void *contents, size_t size)
 	char strings[] = "\0.shstrtab\0.ctf";
 	int fd;
 
-	/* Kernel archives are ELF files containing a .ctf section. */
+	/* Wrap CTF data in an ELF file containing a .ctf section. */
 	CHECK(elf_version(EV_CURRENT) != EV_NONE);
 	CHECK((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0);
 	CHECK((elf = elf_begin(fd, ELF_C_WRITE, NULL)) != NULL);
@@ -91,7 +91,7 @@ write_elf(const char *path, void *contents, size_t size)
 }
 
 static int
-write_archive(const char *path, const char *embedded)
+write_archive(const char *path, const char *embedded, const char *rawpath)
 {
 	ctf_dict_t *dicts[2];
 	const char *names[] = { "shared_ctf", "vmlinux" };
@@ -134,6 +134,9 @@ write_archive(const char *path, const char *embedded)
 	ctf_close(dicts[0]);
 
 	CHECK(write_elf(path, contents, size) == 0);
+	CHECK((raw = fopen(rawpath, "wb")) != NULL);
+	CHECK(fwrite(contents, size, 1, raw) == 1);
+	CHECK(fclose(raw) == 0);
 	free(contents);
 	return 0;
 }
@@ -307,16 +310,20 @@ main(int argc, char **argv)
 {
 #ifdef HAVE_LIBCTF
 	char archive[PATH_MAX], btf[PATH_MAX], missing[PATH_MAX], embedded[PATH_MAX];
+	char raw[PATH_MAX];
 
 	CHECK(argc == 2);
 	snprintf(archive, sizeof(archive), "%s/test.ctfa", argv[1]);
 	snprintf(btf, sizeof(btf), "%s/vmlinux", argv[1]);
 	snprintf(missing, sizeof(missing), "%s/missing.ctfa", argv[1]);
 	snprintf(embedded, sizeof(embedded), "%s/ctf.ko", argv[1]);
-	CHECK(write_archive(archive, embedded) == 0);
+	snprintf(raw, sizeof(raw), "%s/raw.ctfa", argv[1]);
+	CHECK(write_archive(archive, embedded, raw) == 0);
 	CHECK(write_btf(btf) == 0);
 	CHECK(check_source(archive, "none", 1, 0) == 0);
 	CHECK(check_source(archive, "none", 1, 1) == 0);
+	CHECK(check_source(raw, "none", 1, 0) == 0);
+	CHECK(check_source(raw, "none", 1, 1) == 0);
 	CHECK(check_source(missing, argv[1], 0, 0) == 0);
 	CHECK(check_source(missing, argv[1], 0, 1) == 0);
 	CHECK(check_embedded(missing, embedded) == 0);
-- 
2.52.0


                 reply	other threads:[~2026-11-09 20:10 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8ae83c7a93f20b725d46fd3553a21c1b@oracle.com \
    --to=kris.van.hees@oracle.com \
    --cc=dtrace-devel@oss.oracle.com \
    --cc=dtrace@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox