Print this page
11584 ::xcall would be useful
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>

@@ -22,11 +22,11 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /*
  * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
- * Copyright (c) 2015, Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc.
  */
 
 #include <mdb/mdb_ctf.h>
 #include <mdb/mdb_ctf_impl.h>
 #include <mdb/mdb_err.h>

@@ -1234,12 +1234,13 @@
 
         (void) mdb_snprintf(tgtname, sizeof (tgtname),
             "member %s of type %s", name, mp->m_tgtname);
 
         if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
-                mdb_ctf_warn(mp->m_flags,
-                    "could not find %s\n", tgtname);
+                if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT)
+                        return (0);
+                mdb_ctf_warn(mp->m_flags, "could not find %s\n", tgtname);
                 return (set_errno(EMDB_CTFNOMEMB));
         }
 
         return (vread_helper(modmid, modbuf + modoff / NBBY,
             tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags));

@@ -1610,16 +1611,15 @@
  * Enums will also be translated by name, so the mdb module will receive
  * the enum value it expects even if the target has renumbered the enum.
  * Warning: it will therefore only work with enums are only used to store
  * legitimate enum values (not several values or-ed together).
  *
- * By default, if mdb_ctf_vread() can not find any members or enum values,
- * it will print a descriptive message (with mdb_warn()) and fail.
- * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message.
- * Additional flags can be used to ignore specific types of translation
- * failure, but should be used with caution, because they will silently leave
- * the caller's buffer uninitialized.
+ * Flags values:
+ *
+ * MDB_CTF_VREAD_QUIET: keep quiet about failures
+ * MDB_CTF_VREAD_IGNORE_ABSENT: ignore any member that couldn't be found in the
+ * target struct; be careful not to use an uninitialized result.
  */
 int
 mdb_ctf_vread(void *modbuf, const char *target_typename,
     const char *mdb_typename, uintptr_t addr, uint_t flags)
 {

@@ -1628,10 +1628,11 @@
         void *tgtbuf;
         size_t size;
         mdb_ctf_id_t tgtid;
         mdb_ctf_id_t modid;
         mdb_module_t *mod;
+        int ret;
 
         if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
                 mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
                     mod->mod_name);
                 return (set_errno(EMDB_NOCTF));

@@ -1660,19 +1661,24 @@
                 mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
                     target_typename);
                 return (-1); /* errno is set for us */
         }
 
-        tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
+        tgtbuf = mdb_alloc(size, UM_SLEEP);
 
         if (mdb_vread(tgtbuf, size, addr) < 0) {
                 mdb_ctf_warn(flags, "couldn't read %s from %p\n",
                     target_typename, addr);
+                mdb_free(tgtbuf, size);
                 return (-1); /* errno is set for us */
         }
 
-        return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags));
+        ret = vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags);
+
+        mdb_free(tgtbuf, size);
+
+        return (ret);
 }
 
 /*
  * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
  * of the target's type vs the mdb module's type.  Use with complicated