Print this page
4474 DTrace Userland CTF Support
4475 DTrace userland Keyword
4476 DTrace tests should be better citizens
4479 pid provider types
4480 dof emulation missing checks
Reviewed by: Bryan Cantrill <bryan@joyent.com>

@@ -23,11 +23,11 @@
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /*
- * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  */
 
 #include <ctf_impl.h>
 #include <sys/mman.h>
 #include <sys/zmod.h>

@@ -786,10 +786,96 @@
         ctf_close(fp);
         return (NULL);
 }
 
 /*
+ * Dupliate a ctf_file_t and its underlying section information into a new
+ * container. This works by copying the three ctf_sect_t's of the original
+ * container if they exist and passing those into ctf_bufopen. To copy those, we
+ * mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not
+ * the cheapest thing, but it's what we've got.
+ */
+ctf_file_t *
+ctf_dup(ctf_file_t *ofp)
+{
+        ctf_file_t *fp;
+        ctf_sect_t ctfsect, symsect, strsect;
+        ctf_sect_t *ctp, *symp, *strp;
+        void *cbuf, *symbuf, *strbuf;
+        int err;
+
+        cbuf = symbuf = strbuf = NULL;
+        /*
+         * The ctfsect isn't allowed to not exist, but the symbol and string
+         * section might not. We only need to copy the data of the section, not
+         * the name, as ctf_bufopen will take care of that.
+         */
+        bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t));
+        cbuf = ctf_data_alloc(ctfsect.cts_size);
+        if (cbuf == NULL) {
+                (void) ctf_set_errno(ofp, ECTF_MMAP);
+                return (NULL);
+        }
+
+        bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size);
+        ctf_data_protect(cbuf, ctfsect.cts_size);
+        ctfsect.cts_data = cbuf;
+        ctfsect.cts_offset = 0;
+        ctp = &ctfsect;
+
+        if (ofp->ctf_symtab.cts_data != NULL) {
+                bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t));
+                symbuf = ctf_data_alloc(symsect.cts_size);
+                if (symbuf == NULL) {
+                        (void) ctf_set_errno(ofp, ECTF_MMAP);
+                        goto err;
+                }
+                bcopy(symsect.cts_data, symbuf, symsect.cts_size);
+                ctf_data_protect(symbuf, symsect.cts_size);
+                symsect.cts_data = symbuf;
+                symsect.cts_offset = 0;
+                symp = &symsect;
+        } else {
+                symp = NULL;
+        }
+
+        if (ofp->ctf_strtab.cts_data != NULL) {
+                bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t));
+                strbuf = ctf_data_alloc(strsect.cts_size);
+                if (strbuf == NULL) {
+                        (void) ctf_set_errno(ofp, ECTF_MMAP);
+                        goto err;
+                }
+                bcopy(strsect.cts_data, strbuf, strsect.cts_size);
+                ctf_data_protect(strbuf, strsect.cts_size);
+                strsect.cts_data = strbuf;
+                strsect.cts_offset = 0;
+                strp = &strsect;
+        } else {
+                strp = NULL;
+        }
+
+        fp = ctf_bufopen(ctp, symp, strp, &err);
+        if (fp == NULL) {
+                (void) ctf_set_errno(ofp, err);
+                goto err;
+        }
+
+        fp->ctf_flags |= LCTF_MMAP;
+
+        return (fp);
+
+err:
+        ctf_data_free(cbuf, ctfsect.cts_size);
+        if (symbuf != NULL)
+                ctf_data_free(symbuf, symsect.cts_size);
+        if (strbuf != NULL)
+                ctf_data_free(strbuf, strsect.cts_size);
+        return (NULL);
+}
+
+/*
  * Close the specified CTF container and free associated data structures.  Note
  * that ctf_close() is a reference counted operation: if the specified file is
  * the parent of other active containers, its reference count will be greater
  * than one and it will be freed later when no active children exist.
  */