Author: delphij
Date: Fri Aug 23 23:21:24 2013
New Revision: 254744
URL: http://svnweb.freebsd.org/changeset/base/254744

Log:
  MFV r254422:
  
  Illumos DTrace issues:
    3089 want ::typedef
    3094 libctf should support removing a dynamic type
    3095 libctf does not validate arrays correctly
    3096 libctf does not validate function types correctly

Modified:
  head/cddl/contrib/opensolaris/common/ctf/ctf_create.c
  head/cddl/contrib/opensolaris/common/ctf/ctf_error.c
  head/cddl/contrib/opensolaris/common/ctf/ctf_impl.h
  head/cddl/contrib/opensolaris/common/ctf/ctf_open.c
  head/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h
Directory Properties:
  head/cddl/contrib/opensolaris/   (props changed)
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: head/cddl/contrib/opensolaris/common/ctf/ctf_create.c
==============================================================================
--- head/cddl/contrib/opensolaris/common/ctf/ctf_create.c       Fri Aug 23 
23:12:16 2013        (r254743)
+++ head/cddl/contrib/opensolaris/common/ctf/ctf_create.c       Fri Aug 23 
23:21:24 2013        (r254744)
@@ -24,13 +24,15 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident  "%Z%%M% %I%     %E% SMI"
+/*
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ */
 
 #include <sys/sysmacros.h>
 #include <sys/param.h>
 #include <sys/mman.h>
 #include <ctf_impl.h>
+#include <sys/debug.h>
 
 /*
  * This static string is used as the template for initially populating a
@@ -167,6 +169,51 @@ ctf_copy_membnames(ctf_dtdef_t *dtd, uch
 }
 
 /*
+ * Only types of dyanmic CTF containers contain reference counts. These
+ * containers are marked RD/WR. Because of that we basically make this a no-op
+ * for compatability with non-dynamic CTF sections. This is also a no-op for
+ * types which are not dynamic types. It is the responsibility of the caller to
+ * make sure it is a valid type. We help that caller out on debug builds.
+ *
+ * Note that the reference counts are not maintained for types that are not
+ * within this container. In other words if we have a type in a parent, that
+ * will not have its reference count increased. On the flip side, the parent
+ * will not be allowed to remove dynamic types if it has children.
+ */
+static void
+ctf_ref_inc(ctf_file_t *fp, ctf_id_t tid)
+{
+       ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
+
+       if (dtd == NULL)
+               return;
+
+       if (!(fp->ctf_flags & LCTF_RDWR))
+               return;
+
+       dtd->dtd_ref++;
+}
+
+/*
+ * Just as with ctf_ref_inc, this is a no-op on non-writeable containers and 
the
+ * caller should ensure that this is already a valid type.
+ */
+static void
+ctf_ref_dec(ctf_file_t *fp, ctf_id_t tid)
+{
+       ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
+
+       if (dtd == NULL)
+               return;
+
+       if (!(fp->ctf_flags & LCTF_RDWR))
+               return;
+
+       ASSERT(dtd->dtd_ref >= 1);
+       dtd->dtd_ref--;
+}
+
+/*
  * If the specified CTF container is writable and has been modified, reload
  * this container with the updated type definitions.  In order to make this
  * code and the rest of libctf as simple as possible, we perform updates by
@@ -180,6 +227,10 @@ ctf_copy_membnames(ctf_dtdef_t *dtd, uch
  * ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp
  * constant for the caller, so after ctf_bufopen() returns, we use bcopy to
  * swap the interior of the old and new ctf_file_t's, and then free the old.
+ *
+ * Note that the lists of dynamic types stays around and the resulting 
container
+ * is still writeable. Furthermore, the reference counts that are on the dtd's
+ * are still valid.
  */
 int
 ctf_update(ctf_file_t *fp)
@@ -432,6 +483,7 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef
        ctf_dtdef_t *p, **q = &fp->ctf_dthash[h];
        ctf_dmdef_t *dmd, *nmd;
        size_t len;
+       int kind, i;
 
        for (p = *q; p != NULL; p = p->dtd_hash) {
                if (p != dtd)
@@ -443,7 +495,8 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef
        if (p != NULL)
                *q = p->dtd_hash;
 
-       switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) {
+       kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
+       switch (kind) {
        case CTF_K_STRUCT:
        case CTF_K_UNION:
        case CTF_K_ENUM:
@@ -454,14 +507,33 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef
                                ctf_free(dmd->dmd_name, len);
                                fp->ctf_dtstrlen -= len;
                        }
+                       if (kind != CTF_K_ENUM)
+                               ctf_ref_dec(fp, dmd->dmd_type);
                        nmd = ctf_list_next(dmd);
                        ctf_free(dmd, sizeof (ctf_dmdef_t));
                }
                break;
        case CTF_K_FUNCTION:
+               ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
+               for (i = 0; i < CTF_INFO_VLEN(dtd->dtd_data.ctt_info); i++)
+                       if (dtd->dtd_u.dtu_argv[i] != 0)
+                               ctf_ref_dec(fp, dtd->dtd_u.dtu_argv[i]);
                ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
                    CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
                break;
+       case CTF_K_ARRAY:
+               ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
+               ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
+               break;
+       case CTF_K_TYPEDEF:
+               ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
+               break;
+       case CTF_K_POINTER:
+       case CTF_K_VOLATILE:
+       case CTF_K_CONST:
+       case CTF_K_RESTRICT:
+               ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
+               break;
        }
 
        if (dtd->dtd_name) {
@@ -495,7 +567,9 @@ ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t 
  * Discard all of the dynamic type definitions that have been added to the
  * container since the last call to ctf_update().  We locate such types by
  * scanning the list and deleting elements that have type IDs greater than
- * ctf_dtoldid, which is set by ctf_update(), above.
+ * ctf_dtoldid, which is set by ctf_update(), above. Note that to work properly
+ * with our reference counting schemes, we must delete the dynamic list in
+ * reverse.
  */
 int
 ctf_discard(ctf_file_t *fp)
@@ -508,11 +582,11 @@ ctf_discard(ctf_file_t *fp)
        if (!(fp->ctf_flags & LCTF_DIRTY))
                return (0); /* no update required */
 
-       for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
+       for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
                if (dtd->dtd_type <= fp->ctf_dtoldid)
                        continue; /* skip types that have been committed */
 
-               ntd = ctf_list_next(dtd);
+               ntd = ctf_list_prev(dtd);
                ctf_dtd_delete(fp, dtd);
        }
 
@@ -614,6 +688,8 @@ ctf_add_reftype(ctf_file_t *fp, uint_t f
        if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
                return (CTF_ERR); /* errno is set for us */
 
+       ctf_ref_inc(fp, ref);
+
        dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
        dtd->dtd_data.ctt_type = (ushort_t)ref;
 
@@ -645,16 +721,29 @@ ctf_add_array(ctf_file_t *fp, uint_t fla
 {
        ctf_dtdef_t *dtd;
        ctf_id_t type;
+       ctf_file_t *fpd;
 
        if (arp == NULL)
                return (ctf_set_errno(fp, EINVAL));
 
+       fpd = fp;
+       if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
+           ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
+               return (ctf_set_errno(fp, ECTF_BADID));
+
+       fpd = fp;
+       if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
+           ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
+               return (ctf_set_errno(fp, ECTF_BADID));
+
        if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
                return (CTF_ERR); /* errno is set for us */
 
        dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0);
        dtd->dtd_data.ctt_size = 0;
        dtd->dtd_u.dtu_arr = *arp;
+       ctf_ref_inc(fp, arp->ctr_contents);
+       ctf_ref_inc(fp, arp->ctr_index);
 
        return (type);
 }
@@ -662,6 +751,7 @@ ctf_add_array(ctf_file_t *fp, uint_t fla
 int
 ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
 {
+       ctf_file_t *fpd;
        ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
 
        if (!(fp->ctf_flags & LCTF_RDWR))
@@ -670,8 +760,22 @@ ctf_set_array(ctf_file_t *fp, ctf_id_t t
        if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
                return (ctf_set_errno(fp, ECTF_BADID));
 
+       fpd = fp;
+       if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
+           ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
+               return (ctf_set_errno(fp, ECTF_BADID));
+
+       fpd = fp;
+       if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
+           ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
+               return (ctf_set_errno(fp, ECTF_BADID));
+
+       ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
+       ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
        fp->ctf_flags |= LCTF_DIRTY;
        dtd->dtd_u.dtu_arr = *arp;
+       ctf_ref_inc(fp, arp->ctr_contents);
+       ctf_ref_inc(fp, arp->ctr_index);
 
        return (0);
 }
@@ -683,7 +787,9 @@ ctf_add_function(ctf_file_t *fp, uint_t 
        ctf_dtdef_t *dtd;
        ctf_id_t type;
        uint_t vlen;
+       int i;
        ctf_id_t *vdat = NULL;
+       ctf_file_t *fpd;
 
        if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 ||
            (ctc->ctc_argc != 0 && argv == NULL))
@@ -696,6 +802,18 @@ ctf_add_function(ctf_file_t *fp, uint_t 
        if (vlen > CTF_MAX_VLEN)
                return (ctf_set_errno(fp, EOVERFLOW));
 
+       fpd = fp;
+       if (ctf_lookup_by_id(&fpd, ctc->ctc_return) == NULL &&
+           ctf_dtd_lookup(fp, ctc->ctc_return) == NULL)
+               return (ctf_set_errno(fp, ECTF_BADID));
+
+       for (i = 0; i < ctc->ctc_argc; i++) {
+               fpd = fp;
+               if (ctf_lookup_by_id(&fpd, argv[i]) == NULL &&
+                   ctf_dtd_lookup(fp, argv[i]) == NULL)
+                       return (ctf_set_errno(fp, ECTF_BADID));
+       }
+
        if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL)
                return (ctf_set_errno(fp, EAGAIN));
 
@@ -707,6 +825,10 @@ ctf_add_function(ctf_file_t *fp, uint_t 
        dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen);
        dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return;
 
+       ctf_ref_inc(fp, ctc->ctc_return);
+       for (i = 0; i < ctc->ctc_argc; i++)
+               ctf_ref_inc(fp, argv[i]);
+
        bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc);
        if (ctc->ctc_flags & CTF_FUNC_VARARG)
                vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */
@@ -825,8 +947,11 @@ ctf_add_typedef(ctf_file_t *fp, uint_t f
 {
        ctf_dtdef_t *dtd;
        ctf_id_t type;
+       ctf_file_t *fpd;
 
-       if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+       fpd = fp;
+       if (ref == CTF_ERR || (ctf_lookup_by_id(&fpd, ref) == NULL &&
+           ctf_dtd_lookup(fp, ref) == NULL))
                return (ctf_set_errno(fp, EINVAL));
 
        if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
@@ -834,6 +959,7 @@ ctf_add_typedef(ctf_file_t *fp, uint_t f
 
        dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0);
        dtd->dtd_data.ctt_type = (ushort_t)ref;
+       ctf_ref_inc(fp, ref);
 
        return (type);
 }
@@ -1008,6 +1134,45 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t 
        if (s != NULL)
                fp->ctf_dtstrlen += strlen(s) + 1;
 
+       ctf_ref_inc(fp, type);
+       fp->ctf_flags |= LCTF_DIRTY;
+       return (0);
+}
+
+/*
+ * This removes a type from the dynamic section. This will fail if the type is
+ * referenced by another type. Note that the CTF ID is never reused currently 
by
+ * CTF. Note that if this container is a parent container then we just outright
+ * refuse to remove the type. There currently is no notion of searching for the
+ * ctf_dtdef_t in parent containers. If there is, then this constraint could
+ * become finer grained.
+ */
+int
+ctf_delete_type(ctf_file_t *fp, ctf_id_t type)
+{
+       ctf_file_t *fpd;
+       ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
+
+       if (!(fp->ctf_flags & LCTF_RDWR))
+               return (ctf_set_errno(fp, ECTF_RDONLY));
+
+       /*
+        * We want to give as useful an errno as possible. That means that we
+        * want to distinguish between a type which does not exist and one for
+        * which the type is not dynamic.
+        */
+       fpd = fp;
+       if (ctf_lookup_by_id(&fpd, type) == NULL &&
+           ctf_dtd_lookup(fp, type) == NULL)
+               return (CTF_ERR); /* errno is set for us */
+
+       if (dtd == NULL)
+               return (ctf_set_errno(fp, ECTF_NOTDYN));
+
+       if (dtd->dtd_ref != 0 || fp->ctf_refcnt > 1)
+               return (ctf_set_errno(fp, ECTF_REFERENCED));
+
+       ctf_dtd_delete(fp, dtd);
        fp->ctf_flags |= LCTF_DIRTY;
        return (0);
 }
@@ -1103,6 +1268,9 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_fil
        ctf_hash_t *hp;
        ctf_helem_t *hep;
 
+       if (dst_fp == src_fp)
+               return (src_type);
+
        if (!(dst_fp->ctf_flags & LCTF_RDWR))
                return (ctf_set_errno(dst_fp, ECTF_RDONLY));
 
@@ -1313,6 +1481,14 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_fil
 
                if (errs)
                        return (CTF_ERR); /* errno is set for us */
+
+               /*
+                * Now that we know that we can't fail, we go through and bump
+                * all the reference counts on the member types.
+                */
+               for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
+                   dmd != NULL; dmd = ctf_list_next(dmd))
+                       ctf_ref_inc(dst_fp, dmd->dmd_type);
                break;
        }
 

Modified: head/cddl/contrib/opensolaris/common/ctf/ctf_error.c
==============================================================================
--- head/cddl/contrib/opensolaris/common/ctf/ctf_error.c        Fri Aug 23 
23:12:16 2013        (r254743)
+++ head/cddl/contrib/opensolaris/common/ctf/ctf_error.c        Fri Aug 23 
23:21:24 2013        (r254744)
@@ -23,8 +23,9 @@
  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident  "%Z%%M% %I%     %E% SMI"
+/*
+ * Copyright (c) 2012, Joyent, Inc.
+ */
 
 #include <ctf_impl.h>
 
@@ -73,6 +74,8 @@ static const char *const _ctf_errlist[] 
        "Limit on number of dynamic types reached",      /* ECTF_FULL */
        "Duplicate member name definition",              /* ECTF_DUPMEMBER */
        "Conflicting type is already defined",           /* ECTF_CONFLICT */
+       "Type has outstanding references",               /* ECTF_REFERENCED */
+       "Type is not a dynamic type"                     /* ECTF_NOTDYN */
 };
 
 static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]);

Modified: head/cddl/contrib/opensolaris/common/ctf/ctf_impl.h
==============================================================================
--- head/cddl/contrib/opensolaris/common/ctf/ctf_impl.h Fri Aug 23 23:12:16 
2013        (r254743)
+++ head/cddl/contrib/opensolaris/common/ctf/ctf_impl.h Fri Aug 23 23:21:24 
2013        (r254744)
@@ -24,12 +24,13 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #ifndef        _CTF_IMPL_H
 #define        _CTF_IMPL_H
 
-#pragma ident  "%Z%%M% %I%     %E% SMI"
-
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <sys/sysmacros.h>
@@ -149,6 +150,7 @@ typedef struct ctf_dtdef {
        char *dtd_name;         /* name associated with definition (if any) */
        ctf_id_t dtd_type;      /* type identifier for this definition */
        ctf_type_t dtd_data;    /* type node (see <sys/ctf.h>) */
+       int dtd_ref;            /* recfount for dyanmic types */
        union {
                ctf_list_t dtu_members; /* struct, union, or enum */
                ctf_arinfo_t dtu_arr;   /* array */
@@ -269,7 +271,9 @@ enum {
        ECTF_DTFULL,            /* CTF type is full (no more members allowed) */
        ECTF_FULL,              /* CTF container is full */
        ECTF_DUPMEMBER,         /* duplicate member name definition */
-       ECTF_CONFLICT           /* conflicting type definition present */
+       ECTF_CONFLICT,          /* conflicting type definition present */
+       ECTF_REFERENCED,        /* type has outstanding references */
+       ECTF_NOTDYN             /* type is not a dynamic type */
 };
 
 extern ssize_t ctf_get_ctt_size(const ctf_file_t *, const ctf_type_t *,

Modified: head/cddl/contrib/opensolaris/common/ctf/ctf_open.c
==============================================================================
--- head/cddl/contrib/opensolaris/common/ctf/ctf_open.c Fri Aug 23 23:12:16 
2013        (r254743)
+++ head/cddl/contrib/opensolaris/common/ctf/ctf_open.c Fri Aug 23 23:21:24 
2013        (r254744)
@@ -24,8 +24,9 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident  "%Z%%M% %I%     %E% SMI"
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #include <ctf_impl.h>
 #include <sys/mman.h>
@@ -810,8 +811,12 @@ ctf_close(ctf_file_t *fp)
        if (fp->ctf_parent != NULL)
                ctf_close(fp->ctf_parent);
 
-       for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
-               ntd = ctf_list_next(dtd);
+       /*
+        * Note, to work properly with reference counting on the dynamic
+        * section, we must delete the list in reverse.
+        */
+       for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
+               ntd = ctf_list_prev(dtd);
                ctf_dtd_delete(fp, dtd);
        }
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h  Fri Aug 23 
23:12:16 2013        (r254743)
+++ head/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h  Fri Aug 23 
23:21:24 2013        (r254744)
@@ -23,6 +23,9 @@
  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * This header file defines the interfaces available from the CTF debugger
@@ -40,8 +43,6 @@
 #ifndef        _CTF_API_H
 #define        _CTF_API_H
 
-#pragma ident  "%Z%%M% %I%     %E% SMI"
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/elf.h>
@@ -227,6 +228,8 @@ extern int ctf_add_member(ctf_file_t *, 
 
 extern int ctf_set_array(ctf_file_t *, ctf_id_t, const ctf_arinfo_t *);
 
+extern int ctf_delete_type(ctf_file_t *, ctf_id_t);
+
 extern int ctf_update(ctf_file_t *);
 extern int ctf_discard(ctf_file_t *);
 extern int ctf_write(ctf_file_t *, int);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to