Print this page
libdtrace: attempt to resolve FORWARD types to concrete types
1730 DTrace should ignore type information from modules with cth_parlabel mismatches
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>
Reviewed by: Adam Leventhal <ahl@delphix.com>

@@ -841,10 +841,21 @@
                         if (pmp == NULL)
                                 (void) dt_set_errno(dtp, EDT_NOMEM);
                         goto err;
                 }
 
+                /*
+                 * If the label we claim the parent must have is not actually
+                 * present in the parent module, ignore the CTF entirely
+                 * rather than acquiring possibly bad type references.
+                 */
+                if (ctf_label_info(pfp, ctf_parent_label(dmp->dm_ctfp),
+                    NULL) == CTF_ERR) {
+                        (void) dt_set_errno(dtp, EDT_BADCTF);
+                        goto err;
+                }
+
                 if (ctf_import(dmp->dm_ctfp, pfp) == CTF_ERR) {
                         dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);
                         (void) dt_set_errno(dtp, EDT_CTF);
                         goto err;
                 }

@@ -854,10 +865,12 @@
             dmp->dm_name, (void *)dmp->dm_ctfp);
 
         return (dmp->dm_ctfp);
 
 err:
+        dt_dprintf("could not load CTF container for %s: %s\n",
+            dmp->dm_name, dtrace_errmsg(dtp, dtrace_errno(dtp)));
         ctf_close(dmp->dm_ctfp);
         dmp->dm_ctfp = NULL;
         return (NULL);
 }
 

@@ -1370,10 +1383,43 @@
         }
 
         return (0);
 }
 
+boolean_t
+dt_is_forward_decl(ctf_file_t *file, ctf_id_t type)
+{
+        ctf_id_t kind = ctf_type_kind(file, type);
+
+        while ((type = ctf_type_reference(file, type)) != CTF_ERR) {
+                type = ctf_type_resolve(file, type);
+                kind = ctf_type_kind(file, type);
+        }
+
+        return (kind == CTF_K_FORWARD);
+}
+
+void
+dt_resolve_forward_decl(ctf_file_t **ctfp, ctf_id_t *type)
+{
+        char name[DT_TYPE_NAMELEN];
+
+        while (dt_is_forward_decl(*ctfp, *type)) {
+                char *tag = ctf_type_name(*ctfp, *type, name, sizeof (name));
+                dtrace_typeinfo_t dtt;
+
+                if (tag != NULL && dt_type_lookup(tag, &dtt) == 0 &&
+                    (dtt.dtt_ctfp != *ctfp) || dtt.dtt_type != *type) {
+                        *ctfp = dtt.dtt_ctfp;
+                        *type = dtt.dtt_type;
+                } else {
+                        /* All we have is the forward definition */
+                        break;
+                }
+        }
+}
+
 int
 dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
     dtrace_typeinfo_t *tip)
 {
         dtrace_typeinfo_t ti;

@@ -1461,12 +1507,11 @@
                 }
                 if (id != CTF_ERR) {
                         tip->dtt_object = dmp->dm_name;
                         tip->dtt_ctfp = fp;
                         tip->dtt_type = id;
-                        if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
-                            CTF_K_FORWARD)
+                        if (!dt_is_forward_decl(fp, ctf_type_resolve(fp, id)))
                                 return (0);
 
                         found++;
                 }
         }