7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
27 * Copyright (c) 2015, Joyent, Inc. All rights reserved.
28 */
29
30 #include <mdb/mdb_ctf.h>
31 #include <mdb/mdb_ctf_impl.h>
32 #include <mdb/mdb_err.h>
33 #include <mdb/mdb_modapi.h>
34 #include <mdb/mdb_string.h>
35 #include <mdb/mdb.h>
36 #include <mdb/mdb_debug.h>
37
38 #include <libctf.h>
39 #include <string.h>
40 #include <limits.h>
41
42 typedef struct tnarg {
43 mdb_tgt_t *tn_tgt; /* target to use for lookup */
44 const char *tn_name; /* query string to lookup */
45 ctf_file_t *tn_fp; /* CTF container from match */
46 ctf_id_t tn_id; /* CTF type ID from match */
47 } tnarg_t;
1219 uint_t m_flags;
1220 } member_t;
1221
1222 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *,
1223 const char *, uint_t);
1224
1225 static int
1226 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
1227 {
1228 member_t *mp = data;
1229 char *modbuf = mp->m_modbuf;
1230 mdb_ctf_id_t tgtmid;
1231 char *tgtbuf = mp->m_tgtbuf;
1232 ulong_t tgtoff;
1233 char tgtname[128];
1234
1235 (void) mdb_snprintf(tgtname, sizeof (tgtname),
1236 "member %s of type %s", name, mp->m_tgtname);
1237
1238 if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
1239 mdb_ctf_warn(mp->m_flags,
1240 "could not find %s\n", tgtname);
1241 return (set_errno(EMDB_CTFNOMEMB));
1242 }
1243
1244 return (vread_helper(modmid, modbuf + modoff / NBBY,
1245 tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags));
1246 }
1247
1248 typedef struct enum_value {
1249 int *ev_modbuf;
1250 const char *ev_name;
1251 } enum_value_t;
1252
1253 static int
1254 enum_cb(const char *name, int value, void *data)
1255 {
1256 enum_value_t *ev = data;
1257
1258 if (strcmp(name, ev->ev_name) == 0) {
1259 *ev->ev_modbuf = value;
1260 return (1);
1595 * int io_error;
1596 * } mdb_zio_t;
1597 *
1598 * mdb_zio_t zio;
1599 * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0);
1600 *
1601 * If a given MDB module has different dcmds or walkers that need to read
1602 * different members from the same struct, then different "mdb_" types
1603 * should be declared for each caller. By convention, these types should
1604 * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t
1605 * for ::findstack. If the MDB module is compiled from several source files,
1606 * one must be especially careful to not define different types with the
1607 * same name in different source files, because the compiler can not detect
1608 * this error.
1609 *
1610 * Enums will also be translated by name, so the mdb module will receive
1611 * the enum value it expects even if the target has renumbered the enum.
1612 * Warning: it will therefore only work with enums are only used to store
1613 * legitimate enum values (not several values or-ed together).
1614 *
1615 * By default, if mdb_ctf_vread() can not find any members or enum values,
1616 * it will print a descriptive message (with mdb_warn()) and fail.
1617 * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message.
1618 * Additional flags can be used to ignore specific types of translation
1619 * failure, but should be used with caution, because they will silently leave
1620 * the caller's buffer uninitialized.
1621 */
1622 int
1623 mdb_ctf_vread(void *modbuf, const char *target_typename,
1624 const char *mdb_typename, uintptr_t addr, uint_t flags)
1625 {
1626 ctf_file_t *mfp;
1627 ctf_id_t mid;
1628 void *tgtbuf;
1629 size_t size;
1630 mdb_ctf_id_t tgtid;
1631 mdb_ctf_id_t modid;
1632 mdb_module_t *mod;
1633
1634 if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
1635 mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
1636 mod->mod_name);
1637 return (set_errno(EMDB_NOCTF));
1638 }
1639
1640 if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) {
1641 mdb_ctf_warn(flags, "couldn't find ctf data for "
1642 "type %s in mdb module %s\n",
1643 mdb_typename, mod->mod_name);
1644 return (set_errno(ctf_to_errno(ctf_errno(mfp))));
1645 }
1646
1647 set_ctf_id(&modid, mfp, mid);
1648
1649 if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) {
1650 mdb_ctf_warn(flags,
1651 "couldn't find type %s in target's ctf data\n",
1652 target_typename);
1653 return (set_errno(EMDB_NOCTF));
1654 }
1655
1656 /*
1657 * Read the data out of the target's address space.
1658 */
1659 if ((size = mdb_ctf_type_size(tgtid)) == -1UL) {
1660 mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
1661 target_typename);
1662 return (-1); /* errno is set for us */
1663 }
1664
1665 tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
1666
1667 if (mdb_vread(tgtbuf, size, addr) < 0) {
1668 mdb_ctf_warn(flags, "couldn't read %s from %p\n",
1669 target_typename, addr);
1670 return (-1); /* errno is set for us */
1671 }
1672
1673 return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags));
1674 }
1675
1676 /*
1677 * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
1678 * of the target's type vs the mdb module's type. Use with complicated
1679 * types (e.g. structs) may result in unnecessary failure if a member of
1680 * the struct has been changed in the target, but is not actually needed
1681 * by the mdb module. Use mdb_lookup_by_name() + mdb_ctf_vread() to
1682 * avoid this problem.
1683 */
1684 int
1685 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
1686 {
1687 GElf_Sym sym;
1688
1689 if (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, name, &sym) != 0) {
1690 mdb_ctf_warn(flags, "couldn't find symbol %s\n", name);
1691 return (-1); /* errno is set for us */
1692 }
1693
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
27 * Copyright (c) 2018, Joyent, Inc.
28 */
29
30 #include <mdb/mdb_ctf.h>
31 #include <mdb/mdb_ctf_impl.h>
32 #include <mdb/mdb_err.h>
33 #include <mdb/mdb_modapi.h>
34 #include <mdb/mdb_string.h>
35 #include <mdb/mdb.h>
36 #include <mdb/mdb_debug.h>
37
38 #include <libctf.h>
39 #include <string.h>
40 #include <limits.h>
41
42 typedef struct tnarg {
43 mdb_tgt_t *tn_tgt; /* target to use for lookup */
44 const char *tn_name; /* query string to lookup */
45 ctf_file_t *tn_fp; /* CTF container from match */
46 ctf_id_t tn_id; /* CTF type ID from match */
47 } tnarg_t;
1219 uint_t m_flags;
1220 } member_t;
1221
1222 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *,
1223 const char *, uint_t);
1224
1225 static int
1226 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
1227 {
1228 member_t *mp = data;
1229 char *modbuf = mp->m_modbuf;
1230 mdb_ctf_id_t tgtmid;
1231 char *tgtbuf = mp->m_tgtbuf;
1232 ulong_t tgtoff;
1233 char tgtname[128];
1234
1235 (void) mdb_snprintf(tgtname, sizeof (tgtname),
1236 "member %s of type %s", name, mp->m_tgtname);
1237
1238 if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
1239 if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT)
1240 return (0);
1241 mdb_ctf_warn(mp->m_flags, "could not find %s\n", tgtname);
1242 return (set_errno(EMDB_CTFNOMEMB));
1243 }
1244
1245 return (vread_helper(modmid, modbuf + modoff / NBBY,
1246 tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags));
1247 }
1248
1249 typedef struct enum_value {
1250 int *ev_modbuf;
1251 const char *ev_name;
1252 } enum_value_t;
1253
1254 static int
1255 enum_cb(const char *name, int value, void *data)
1256 {
1257 enum_value_t *ev = data;
1258
1259 if (strcmp(name, ev->ev_name) == 0) {
1260 *ev->ev_modbuf = value;
1261 return (1);
1596 * int io_error;
1597 * } mdb_zio_t;
1598 *
1599 * mdb_zio_t zio;
1600 * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0);
1601 *
1602 * If a given MDB module has different dcmds or walkers that need to read
1603 * different members from the same struct, then different "mdb_" types
1604 * should be declared for each caller. By convention, these types should
1605 * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t
1606 * for ::findstack. If the MDB module is compiled from several source files,
1607 * one must be especially careful to not define different types with the
1608 * same name in different source files, because the compiler can not detect
1609 * this error.
1610 *
1611 * Enums will also be translated by name, so the mdb module will receive
1612 * the enum value it expects even if the target has renumbered the enum.
1613 * Warning: it will therefore only work with enums are only used to store
1614 * legitimate enum values (not several values or-ed together).
1615 *
1616 * Flags values:
1617 *
1618 * MDB_CTF_VREAD_QUIET: keep quiet about failures
1619 * MDB_CTF_VREAD_IGNORE_ABSENT: ignore any member that couldn't be found in the
1620 * target struct; be careful not to use an uninitialized result.
1621 */
1622 int
1623 mdb_ctf_vread(void *modbuf, const char *target_typename,
1624 const char *mdb_typename, uintptr_t addr, uint_t flags)
1625 {
1626 ctf_file_t *mfp;
1627 ctf_id_t mid;
1628 void *tgtbuf;
1629 size_t size;
1630 mdb_ctf_id_t tgtid;
1631 mdb_ctf_id_t modid;
1632 mdb_module_t *mod;
1633 int ret;
1634
1635 if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
1636 mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
1637 mod->mod_name);
1638 return (set_errno(EMDB_NOCTF));
1639 }
1640
1641 if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) {
1642 mdb_ctf_warn(flags, "couldn't find ctf data for "
1643 "type %s in mdb module %s\n",
1644 mdb_typename, mod->mod_name);
1645 return (set_errno(ctf_to_errno(ctf_errno(mfp))));
1646 }
1647
1648 set_ctf_id(&modid, mfp, mid);
1649
1650 if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) {
1651 mdb_ctf_warn(flags,
1652 "couldn't find type %s in target's ctf data\n",
1653 target_typename);
1654 return (set_errno(EMDB_NOCTF));
1655 }
1656
1657 /*
1658 * Read the data out of the target's address space.
1659 */
1660 if ((size = mdb_ctf_type_size(tgtid)) == -1UL) {
1661 mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
1662 target_typename);
1663 return (-1); /* errno is set for us */
1664 }
1665
1666 tgtbuf = mdb_alloc(size, UM_SLEEP);
1667
1668 if (mdb_vread(tgtbuf, size, addr) < 0) {
1669 mdb_ctf_warn(flags, "couldn't read %s from %p\n",
1670 target_typename, addr);
1671 mdb_free(tgtbuf, size);
1672 return (-1); /* errno is set for us */
1673 }
1674
1675 ret = vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags);
1676
1677 mdb_free(tgtbuf, size);
1678
1679 return (ret);
1680 }
1681
1682 /*
1683 * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
1684 * of the target's type vs the mdb module's type. Use with complicated
1685 * types (e.g. structs) may result in unnecessary failure if a member of
1686 * the struct has been changed in the target, but is not actually needed
1687 * by the mdb module. Use mdb_lookup_by_name() + mdb_ctf_vread() to
1688 * avoid this problem.
1689 */
1690 int
1691 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
1692 {
1693 GElf_Sym sym;
1694
1695 if (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, name, &sym) != 0) {
1696 mdb_ctf_warn(flags, "couldn't find symbol %s\n", name);
1697 return (-1); /* errno is set for us */
1698 }
1699
|