Home | History | Annotate | Download | only in mdb
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      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 #include <mdb/mdb_ctf.h>
     27 #include <mdb/mdb_ctf_impl.h>
     28 #include <mdb/mdb_err.h>
     29 #include <mdb/mdb_modapi.h>
     30 #include <mdb/mdb_string.h>
     31 #include <mdb/mdb.h>
     32 #include <mdb/mdb_debug.h>
     33 
     34 #include <libctf.h>
     35 #include <string.h>
     36 
     37 typedef struct tnarg {
     38 	mdb_tgt_t *tn_tgt;		/* target to use for lookup */
     39 	const char *tn_name;		/* query string to lookup */
     40 	ctf_file_t *tn_fp;		/* CTF container from match */
     41 	ctf_id_t tn_id;			/* CTF type ID from match */
     42 } tnarg_t;
     43 
     44 typedef struct type_iter {
     45 	mdb_ctf_type_f *ti_cb;
     46 	void *ti_arg;
     47 	ctf_file_t *ti_fp;
     48 } type_iter_t;
     49 
     50 typedef struct member_iter {
     51 	mdb_ctf_member_f *mi_cb;
     52 	void *mi_arg;
     53 	ctf_file_t *mi_fp;
     54 } member_iter_t;
     55 
     56 typedef struct type_visit {
     57 	mdb_ctf_visit_f	*tv_cb;
     58 	void		*tv_arg;
     59 	ctf_file_t	*tv_fp;
     60 	ulong_t		tv_base_offset;	/* used when recursing from type_cb() */
     61 	int		tv_base_depth;	/* used when recursing from type_cb() */
     62 	int		tv_min_depth;
     63 } type_visit_t;
     64 
     65 typedef struct mbr_info {
     66 	const char *mbr_member;
     67 	ulong_t *mbr_offp;
     68 	mdb_ctf_id_t *mbr_typep;
     69 } mbr_info_t;
     70 
     71 static void
     72 set_ctf_id(mdb_ctf_id_t *p, ctf_file_t *fp, ctf_id_t id)
     73 {
     74 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
     75 
     76 	mcip->mci_fp = fp;
     77 	mcip->mci_id = id;
     78 }
     79 
     80 /*
     81  * Callback function for mdb_tgt_object_iter used from name_to_type, below,
     82  * to search the CTF namespace of each object file for a particular name.
     83  */
     84 /*ARGSUSED*/
     85 static int
     86 obj_lookup(void *data, const mdb_map_t *mp, const char *name)
     87 {
     88 	tnarg_t *tnp = data;
     89 	ctf_file_t *fp;
     90 	ctf_id_t id;
     91 
     92 	if ((fp = mdb_tgt_name_to_ctf(tnp->tn_tgt, name)) != NULL &&
     93 	    (id = ctf_lookup_by_name(fp, tnp->tn_name)) != CTF_ERR) {
     94 		tnp->tn_fp = fp;
     95 		tnp->tn_id = id;
     96 
     97 		/*
     98 		 * We may have found a forward declaration.  If we did, we'll
     99 		 * note the ID and file pointer, but we'll keep searching in
    100 		 * an attempt to find the real thing.  If we found something
    101 		 * real (i.e. not a forward), we stop the iteration.
    102 		 */
    103 		return (ctf_type_kind(fp, id) == CTF_K_FORWARD ? 0 : -1);
    104 	}
    105 
    106 	return (0);
    107 }
    108 
    109 /*
    110  * Convert a string type name with an optional leading object specifier into
    111  * the corresponding CTF file container and type ID.  If an error occurs, we
    112  * print an appropriate message and return NULL.
    113  */
    114 static ctf_file_t *
    115 name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp)
    116 {
    117 	const char *object = MDB_TGT_OBJ_EXEC;
    118 	ctf_file_t *fp = NULL;
    119 	ctf_id_t id;
    120 	tnarg_t arg;
    121 	char *p, *s;
    122 	char buf[MDB_SYM_NAMLEN];
    123 	char *name = &buf[0];
    124 
    125 	(void) mdb_snprintf(buf, sizeof (buf), "%s", cname);
    126 
    127 	if ((p = strrsplit(name, '`')) != NULL) {
    128 		/*
    129 		 * We need to shuffle things around a little to support
    130 		 * type names of the form "struct module`name".
    131 		 */
    132 		if ((s = strsplit(name, ' ')) != NULL) {
    133 			bcopy(cname + (s - name), name, (p - s) - 1);
    134 			name[(p - s) - 1] = '\0';
    135 			bcopy(cname, name + (p - s), s - name);
    136 			p = name + (p - s);
    137 		}
    138 		if (*name != '\0')
    139 			object = name;
    140 		name = p;
    141 	}
    142 
    143 	/*
    144 	 * Attempt to look up the name in the primary object file.  If this
    145 	 * fails and the name was unscoped, search all remaining object files.
    146 	 */
    147 	if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL ||
    148 	    (id = ctf_lookup_by_name(fp, name)) == CTF_ERR ||
    149 	    ctf_type_kind(fp, id) == CTF_K_FORWARD) &&
    150 	    object == MDB_TGT_OBJ_EXEC) {
    151 
    152 		arg.tn_tgt = t;
    153 		arg.tn_name = name;
    154 		arg.tn_fp = NULL;
    155 		arg.tn_id = CTF_ERR;
    156 
    157 		(void) mdb_tgt_object_iter(t, obj_lookup, &arg);
    158 
    159 		if (arg.tn_id != CTF_ERR) {
    160 			fp = arg.tn_fp;
    161 			id = arg.tn_id;
    162 		}
    163 	}
    164 
    165 	if (fp == NULL)
    166 		return (NULL); /* errno is set for us */
    167 
    168 	if (id == CTF_ERR) {
    169 		(void) set_errno(ctf_to_errno(ctf_errno(fp)));
    170 		return (NULL);
    171 	}
    172 
    173 	*idp = id;
    174 	return (fp);
    175 }
    176 
    177 /*
    178  * Check to see if there is ctf data in the given object. This is useful
    179  * so that we don't enter some loop where every call to lookup fails.
    180  */
    181 int
    182 mdb_ctf_enabled_by_object(const char *object)
    183 {
    184 	mdb_tgt_t *t = mdb.m_target;
    185 
    186 	return (mdb_tgt_name_to_ctf(t, object) != NULL);
    187 }
    188 
    189 int
    190 mdb_ctf_lookup_by_name(const char *name, mdb_ctf_id_t *p)
    191 {
    192 	ctf_file_t *fp = NULL;
    193 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
    194 	mdb_tgt_t *t = mdb.m_target;
    195 
    196 	if (mcip == NULL)
    197 		return (set_errno(EINVAL));
    198 
    199 	if ((fp = name_to_type(t, name, &mcip->mci_id)) == NULL) {
    200 		mdb_ctf_type_invalidate(p);
    201 		return (-1); /* errno is set for us */
    202 	}
    203 
    204 	mcip->mci_fp = fp;
    205 
    206 	return (0);
    207 }
    208 
    209 int
    210 mdb_ctf_lookup_by_symbol(const GElf_Sym *symp, const mdb_syminfo_t *sip,
    211     mdb_ctf_id_t *p)
    212 {
    213 	ctf_file_t *fp = NULL;
    214 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
    215 	mdb_tgt_t *t = mdb.m_target;
    216 
    217 	if (mcip == NULL)
    218 		return (set_errno(EINVAL));
    219 
    220 	if (symp == NULL || sip == NULL) {
    221 		mdb_ctf_type_invalidate(p);
    222 		return (set_errno(EINVAL));
    223 	}
    224 
    225 	if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL) {
    226 		mdb_ctf_type_invalidate(p);
    227 		return (-1); /* errno is set for us */
    228 	}
    229 
    230 	if ((mcip->mci_id = ctf_lookup_by_symbol(fp, sip->sym_id)) == CTF_ERR) {
    231 		mdb_ctf_type_invalidate(p);
    232 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
    233 	}
    234 
    235 	mcip->mci_fp = fp;
    236 
    237 	return (0);
    238 }
    239 
    240 int
    241 mdb_ctf_lookup_by_addr(uintptr_t addr, mdb_ctf_id_t *p)
    242 {
    243 	GElf_Sym sym;
    244 	mdb_syminfo_t si;
    245 	char name[MDB_SYM_NAMLEN];
    246 	const mdb_map_t *mp;
    247 	mdb_tgt_t *t = mdb.m_target;
    248 	const char *obj, *c;
    249 
    250 	if (p == NULL)
    251 		return (set_errno(EINVAL));
    252 
    253 	if (mdb_tgt_lookup_by_addr(t, addr, MDB_TGT_SYM_EXACT, name,
    254 	    sizeof (name), NULL, NULL) == -1) {
    255 		mdb_ctf_type_invalidate(p);
    256 		return (-1); /* errno is set for us */
    257 	}
    258 
    259 	if ((c = strrsplit(name, '`')) != NULL) {
    260 		obj = name;
    261 	} else {
    262 		if ((mp = mdb_tgt_addr_to_map(t, addr)) == NULL) {
    263 			mdb_ctf_type_invalidate(p);
    264 			return (-1); /* errno is set for us */
    265 		}
    266 
    267 		obj = mp->map_name;
    268 		c = name;
    269 	}
    270 
    271 	if (mdb_tgt_lookup_by_name(t, obj, c, &sym, &si) == -1) {
    272 		mdb_ctf_type_invalidate(p);
    273 		return (-1); /* errno is set for us */
    274 	}
    275 
    276 	return (mdb_ctf_lookup_by_symbol(&sym, &si, p));
    277 }
    278 
    279 int
    280 mdb_ctf_module_lookup(const char *name, mdb_ctf_id_t *p)
    281 {
    282 	ctf_file_t *fp;
    283 	ctf_id_t id;
    284 	mdb_module_t *mod;
    285 
    286 	if ((mod = mdb_get_module()) == NULL)
    287 		return (set_errno(EMDB_CTX));
    288 
    289 	if ((fp = mod->mod_ctfp) == NULL)
    290 		return (set_errno(EMDB_NOCTF));
    291 
    292 	if ((id = ctf_lookup_by_name(fp, name)) == CTF_ERR)
    293 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
    294 
    295 	set_ctf_id(p, fp, id);
    296 
    297 	return (0);
    298 }
    299 
    300 /*ARGSUSED*/
    301 int
    302 mdb_ctf_func_info(const GElf_Sym *symp, const mdb_syminfo_t *sip,
    303     mdb_ctf_funcinfo_t *mfp)
    304 {
    305 	ctf_file_t *fp = NULL;
    306 	ctf_funcinfo_t f;
    307 	mdb_tgt_t *t = mdb.m_target;
    308 	char name[MDB_SYM_NAMLEN];
    309 	const mdb_map_t *mp;
    310 	mdb_syminfo_t si;
    311 	int err;
    312 
    313 	if (symp == NULL || mfp == NULL)
    314 		return (set_errno(EINVAL));
    315 
    316 	/*
    317 	 * In case the input symbol came from a merged or private symbol table,
    318 	 * re-lookup the address as a symbol, and then perform a fully scoped
    319 	 * lookup of that symbol name to get the mdb_syminfo_t for its CTF.
    320 	 */
    321 	if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL ||
    322 	    (mp = mdb_tgt_addr_to_map(t, symp->st_value)) == NULL ||
    323 	    mdb_tgt_lookup_by_addr(t, symp->st_value, MDB_TGT_SYM_FUZZY,
    324 	    name, sizeof (name), NULL, NULL) != 0)
    325 		return (-1); /* errno is set for us */
    326 
    327 	if (strchr(name, '`') != NULL)
    328 		err = mdb_tgt_lookup_by_scope(t, name, NULL, &si);
    329 	else
    330 		err = mdb_tgt_lookup_by_name(t, mp->map_name, name, NULL, &si);
    331 
    332 	if (err != 0)
    333 		return (-1); /* errno is set for us */
    334 
    335 	if (ctf_func_info(fp, si.sym_id, &f) == CTF_ERR)
    336 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
    337 
    338 	set_ctf_id(&mfp->mtf_return, fp, f.ctc_return);
    339 	mfp->mtf_argc = f.ctc_argc;
    340 	mfp->mtf_flags = f.ctc_flags;
    341 	mfp->mtf_symidx = si.sym_id;
    342 
    343 	return (0);
    344 }
    345 
    346 int
    347 mdb_ctf_func_args(const mdb_ctf_funcinfo_t *funcp, uint_t len,
    348     mdb_ctf_id_t *argv)
    349 {
    350 	ctf_file_t *fp;
    351 	ctf_id_t cargv[32];
    352 	int i;
    353 
    354 	if (len > (sizeof (cargv) / sizeof (cargv[0])))
    355 		return (set_errno(EINVAL));
    356 
    357 	if (funcp == NULL || argv == NULL)
    358 		return (set_errno(EINVAL));
    359 
    360 	fp = mdb_ctf_type_file(funcp->mtf_return);
    361 
    362 	if (ctf_func_args(fp, funcp->mtf_symidx, len, cargv) == CTF_ERR)
    363 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
    364 
    365 	for (i = MIN(len, funcp->mtf_argc) - 1; i >= 0; i--) {
    366 		set_ctf_id(&argv[i], fp, cargv[i]);
    367 	}
    368 
    369 	return (0);
    370 }
    371 
    372 void
    373 mdb_ctf_type_invalidate(mdb_ctf_id_t *idp)
    374 {
    375 	set_ctf_id(idp, NULL, CTF_ERR);
    376 }
    377 
    378 int
    379 mdb_ctf_type_valid(mdb_ctf_id_t id)
    380 {
    381 	return (((mdb_ctf_impl_t *)&id)->mci_id != CTF_ERR);
    382 }
    383 
    384 int
    385 mdb_ctf_type_cmp(mdb_ctf_id_t aid, mdb_ctf_id_t bid)
    386 {
    387 	mdb_ctf_impl_t *aidp = (mdb_ctf_impl_t *)&aid;
    388 	mdb_ctf_impl_t *bidp = (mdb_ctf_impl_t *)&bid;
    389 
    390 	return (ctf_type_cmp(aidp->mci_fp, aidp->mci_id,
    391 	    bidp->mci_fp, bidp->mci_id));
    392 }
    393 
    394 int
    395 mdb_ctf_type_resolve(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
    396 {
    397 	ctf_id_t id;
    398 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&mid;
    399 
    400 	if ((id = ctf_type_resolve(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
    401 		if (outp)
    402 			mdb_ctf_type_invalidate(outp);
    403 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
    404 	}
    405 
    406 	if (ctf_type_kind(idp->mci_fp, id) == CTF_K_FORWARD) {
    407 		char name[MDB_SYM_NAMLEN];
    408 		mdb_ctf_id_t lookup_id;
    409 
    410 		if (ctf_type_name(idp->mci_fp, id, name, sizeof (name)) !=
    411 		    NULL &&
    412 		    mdb_ctf_lookup_by_name(name, &lookup_id) == 0 &&
    413 		    outp != NULL) {
    414 			*outp = lookup_id;
    415 			return (0);
    416 		}
    417 	}
    418 
    419 	if (outp != NULL)
    420 		set_ctf_id(outp, idp->mci_fp, id);
    421 
    422 	return (0);
    423 }
    424 
    425 char *
    426 mdb_ctf_type_name(mdb_ctf_id_t id, char *buf, size_t len)
    427 {
    428 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    429 	char *ret;
    430 
    431 	if (!mdb_ctf_type_valid(id)) {
    432 		(void) set_errno(EINVAL);
    433 		return (NULL);
    434 	}
    435 
    436 	ret = ctf_type_name(idp->mci_fp, idp->mci_id, buf, len);
    437 	if (ret == NULL)
    438 		(void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
    439 
    440 	return (ret);
    441 }
    442 
    443 ssize_t
    444 mdb_ctf_type_size(mdb_ctf_id_t id)
    445 {
    446 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    447 	ssize_t ret;
    448 
    449 	/* resolve the type in case there's a forward declaration */
    450 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
    451 		return (ret);
    452 
    453 	if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR)
    454 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
    455 
    456 	return (ret);
    457 }
    458 
    459 int
    460 mdb_ctf_type_kind(mdb_ctf_id_t id)
    461 {
    462 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    463 	int ret;
    464 
    465 	if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR)
    466 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
    467 
    468 	return (ret);
    469 }
    470 
    471 int
    472 mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
    473 {
    474 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&mid;
    475 	ctf_id_t id;
    476 
    477 	if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
    478 		if (outp)
    479 			mdb_ctf_type_invalidate(outp);
    480 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
    481 	}
    482 
    483 	if (outp != NULL)
    484 		set_ctf_id(outp, idp->mci_fp, id);
    485 
    486 	return (0);
    487 }
    488 
    489 
    490 int
    491 mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep)
    492 {
    493 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    494 
    495 	if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR)
    496 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
    497 
    498 	return (0);
    499 }
    500 
    501 /*
    502  * callback proxy for mdb_ctf_type_visit
    503  */
    504 static int
    505 type_cb(const char *name, ctf_id_t type, ulong_t off, int depth, void *arg)
    506 {
    507 	type_visit_t *tvp = arg;
    508 	mdb_ctf_id_t id;
    509 	mdb_ctf_id_t base;
    510 	mdb_ctf_impl_t *basep = (mdb_ctf_impl_t *)&base;
    511 
    512 	int ret;
    513 
    514 	if (depth < tvp->tv_min_depth)
    515 		return (0);
    516 
    517 	off += tvp->tv_base_offset;
    518 	depth += tvp->tv_base_depth;
    519 
    520 	set_ctf_id(&id, tvp->tv_fp, type);
    521 
    522 	(void) mdb_ctf_type_resolve(id, &base);
    523 	if ((ret = tvp->tv_cb(name, id, base, off, depth, tvp->tv_arg)) != 0)
    524 		return (ret);
    525 
    526 	/*
    527 	 * If the type resolves to a type in a different file, we must have
    528 	 * followed a forward declaration.  We need to recurse into the
    529 	 * new type.
    530 	 */
    531 	if (basep->mci_fp != tvp->tv_fp && mdb_ctf_type_valid(base)) {
    532 		type_visit_t tv;
    533 
    534 		tv.tv_cb = tvp->tv_cb;
    535 		tv.tv_arg = tvp->tv_arg;
    536 		tv.tv_fp = basep->mci_fp;
    537 
    538 		tv.tv_base_offset = off;
    539 		tv.tv_base_depth = depth;
    540 		tv.tv_min_depth = 1;	/* depth = 0 has already been done */
    541 
    542 		ret = ctf_type_visit(basep->mci_fp, basep->mci_id,
    543 		    type_cb, &tv);
    544 	}
    545 	return (ret);
    546 }
    547 
    548 int
    549 mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg)
    550 {
    551 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    552 	type_visit_t tv;
    553 	int ret;
    554 
    555 	tv.tv_cb = func;
    556 	tv.tv_arg = arg;
    557 	tv.tv_fp = idp->mci_fp;
    558 	tv.tv_base_offset = 0;
    559 	tv.tv_base_depth = 0;
    560 	tv.tv_min_depth = 0;
    561 
    562 	ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv);
    563 
    564 	if (ret == CTF_ERR)
    565 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
    566 
    567 	return (ret);
    568 }
    569 
    570 int
    571 mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp)
    572 {
    573 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    574 	ctf_arinfo_t car;
    575 
    576 	if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR)
    577 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
    578 
    579 	set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents);
    580 	set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index);
    581 
    582 	arp->mta_nelems = car.ctr_nelems;
    583 
    584 	return (0);
    585 }
    586 
    587 const char *
    588 mdb_ctf_enum_name(mdb_ctf_id_t id, int value)
    589 {
    590 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    591 	const char *ret;
    592 
    593 	/* resolve the type in case there's a forward declaration */
    594 	if (mdb_ctf_type_resolve(id, &id) != 0)
    595 		return (NULL);
    596 
    597 	if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL)
    598 		(void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
    599 
    600 	return (ret);
    601 }
    602 
    603 /*
    604  * callback proxy for mdb_ctf_member_iter
    605  */
    606 static int
    607 member_iter_cb(const char *name, ctf_id_t type, ulong_t off, void *data)
    608 {
    609 	member_iter_t *mip = data;
    610 	mdb_ctf_id_t id;
    611 
    612 	set_ctf_id(&id, mip->mi_fp, type);
    613 
    614 	return (mip->mi_cb(name, id, off, mip->mi_arg));
    615 }
    616 
    617 int
    618 mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data)
    619 {
    620 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    621 	member_iter_t mi;
    622 	int ret;
    623 
    624 	/* resolve the type in case there's a forward declaration */
    625 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
    626 		return (ret);
    627 
    628 	mi.mi_cb = cb;
    629 	mi.mi_arg = data;
    630 	mi.mi_fp = idp->mci_fp;
    631 
    632 	ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi);
    633 
    634 	if (ret == CTF_ERR)
    635 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
    636 
    637 	return (ret);
    638 }
    639 
    640 int
    641 mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data)
    642 {
    643 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
    644 	int ret;
    645 
    646 	/* resolve the type in case there's a forward declaration */
    647 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
    648 		return (ret);
    649 
    650 	return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data));
    651 }
    652 
    653 /*
    654  * callback proxy for mdb_ctf_type_iter
    655  */
    656 static int
    657 type_iter_cb(ctf_id_t type, void *data)
    658 {
    659 	type_iter_t *tip = data;
    660 	mdb_ctf_id_t id;
    661 
    662 	set_ctf_id(&id, tip->ti_fp, type);
    663 
    664 	return (tip->ti_cb(id, tip->ti_arg));
    665 }
    666 
    667 int
    668 mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data)
    669 {
    670 	ctf_file_t *fp;
    671 	mdb_tgt_t *t = mdb.m_target;
    672 	int ret;
    673 	type_iter_t ti;
    674 
    675 	if ((fp = mdb_tgt_name_to_ctf(t, object)) == NULL)
    676 		return (-1);
    677 
    678 	ti.ti_cb = cb;
    679 	ti.ti_arg = data;
    680 	ti.ti_fp = fp;
    681 
    682 	if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR)
    683 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
    684 
    685 	return (ret);
    686 }
    687 
    688 /* utility functions */
    689 
    690 ctf_id_t
    691 mdb_ctf_type_id(mdb_ctf_id_t id)
    692 {
    693 	return (((mdb_ctf_impl_t *)&id)->mci_id);
    694 }
    695 
    696 ctf_file_t *
    697 mdb_ctf_type_file(mdb_ctf_id_t id)
    698 {
    699 	return (((mdb_ctf_impl_t *)&id)->mci_fp);
    700 }
    701 
    702 static int
    703 member_info_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
    704 {
    705 	mbr_info_t *mbrp = data;
    706 
    707 	if (strcmp(name, mbrp->mbr_member) == 0) {
    708 		if (mbrp->mbr_offp != NULL)
    709 			*(mbrp->mbr_offp) = off;
    710 		if (mbrp->mbr_typep != NULL)
    711 			*(mbrp->mbr_typep) = id;
    712 
    713 		return (1);
    714 	}
    715 
    716 	return (0);
    717 }
    718 
    719 int
    720 mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp,
    721     mdb_ctf_id_t *typep)
    722 {
    723 	mbr_info_t mbr;
    724 	int rc;
    725 
    726 	mbr.mbr_member = member;
    727 	mbr.mbr_offp = offp;
    728 	mbr.mbr_typep = typep;
    729 
    730 	rc = mdb_ctf_member_iter(id, member_info_cb, &mbr);
    731 
    732 	/* couldn't get member list */
    733 	if (rc == -1)
    734 		return (-1); /* errno is set for us */
    735 
    736 	/* not a member */
    737 	if (rc == 0)
    738 		return (set_errno(EMDB_CTFNOMEMB));
    739 
    740 	return (0);
    741 }
    742 
    743 int
    744 mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp)
    745 {
    746 	return (mdb_ctf_member_info(id, member, retp, NULL));
    747 }
    748 
    749 /*ARGSUSED*/
    750 static int
    751 num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
    752 {
    753 	int *count = data;
    754 	*count = *count + 1;
    755 	return (0);
    756 }
    757 
    758 int
    759 mdb_ctf_num_members(mdb_ctf_id_t id)
    760 {
    761 	int count = 0;
    762 
    763 	if (mdb_ctf_member_iter(id, num_members_cb, &count) != 0)
    764 		return (-1); /* errno is set for us */
    765 
    766 	return (count);
    767 }
    768 
    769 typedef struct mbr_contains {
    770 	char **mbc_bufp;
    771 	size_t *mbc_lenp;
    772 	ulong_t *mbc_offp;
    773 	mdb_ctf_id_t *mbc_idp;
    774 	ssize_t mbc_total;
    775 } mbr_contains_t;
    776 
    777 static int
    778 offset_to_name_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
    779 {
    780 	mbr_contains_t *mbc = data;
    781 	ulong_t size;
    782 	ctf_encoding_t e;
    783 	size_t n;
    784 
    785 	if (*mbc->mbc_offp < off)
    786 		return (0);
    787 
    788 	if (mdb_ctf_type_encoding(id, &e) == -1)
    789 		size = mdb_ctf_type_size(id) * NBBY;
    790 	else
    791 		size = e.cte_bits;
    792 
    793 	if (off + size <= *mbc->mbc_offp)
    794 		return (0);
    795 
    796 	n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "%s", name);
    797 	mbc->mbc_total += n;
    798 	if (n > *mbc->mbc_lenp)
    799 		n = *mbc->mbc_lenp;
    800 
    801 	*mbc->mbc_lenp -= n;
    802 	*mbc->mbc_bufp += n;
    803 
    804 	*mbc->mbc_offp -= off;
    805 	*mbc->mbc_idp = id;
    806 
    807 	return (1);
    808 }
    809 
    810 ssize_t
    811 mdb_ctf_offset_to_name(mdb_ctf_id_t id, ulong_t off, char *buf, size_t len,
    812     int dot, mdb_ctf_id_t *midp, ulong_t *moffp)
    813 {
    814 	size_t size;
    815 	size_t n;
    816 	mbr_contains_t mbc;
    817 
    818 	if (!mdb_ctf_type_valid(id))
    819 		return (set_errno(EINVAL));
    820 
    821 	/*
    822 	 * Quick sanity check to make sure the given offset is within
    823 	 * this scope of this type.
    824 	 */
    825 	if (mdb_ctf_type_size(id) * NBBY <= off)
    826 		return (set_errno(EINVAL));
    827 
    828 	mbc.mbc_bufp = &buf;
    829 	mbc.mbc_lenp = &len;
    830 	mbc.mbc_offp = &off;
    831 	mbc.mbc_idp = &id;
    832 	mbc.mbc_total = 0;
    833 
    834 	*buf = '\0';
    835 
    836 	for (;;) {
    837 		/*
    838 		 * Check for an exact match.
    839 		 */
    840 		if (off == 0)
    841 			break;
    842 
    843 		(void) mdb_ctf_type_resolve(id, &id);
    844 
    845 		/*
    846 		 * Find the member that contains this offset.
    847 		 */
    848 		switch (mdb_ctf_type_kind(id)) {
    849 		case CTF_K_ARRAY: {
    850 			mdb_ctf_arinfo_t ar;
    851 			uint_t index;
    852 
    853 			(void) mdb_ctf_array_info(id, &ar);
    854 			size = mdb_ctf_type_size(ar.mta_contents) * NBBY;
    855 			index = off / size;
    856 
    857 			id = ar.mta_contents;
    858 			off %= size;
    859 
    860 			n = mdb_snprintf(buf, len, "[%u]", index);
    861 			mbc.mbc_total += n;
    862 			if (n > len)
    863 				n = len;
    864 
    865 			buf += n;
    866 			len -= n;
    867 			break;
    868 		}
    869 
    870 		case CTF_K_STRUCT: {
    871 			int ret;
    872 
    873 			/*
    874 			 * Find the member that contains this offset
    875 			 * and continue.
    876 			 */
    877 
    878 			if (dot) {
    879 				mbc.mbc_total++;
    880 				if (len != 0) {
    881 					*buf++ = '.';
    882 					*buf = '\0';
    883 					len--;
    884 				}
    885 			}
    886 
    887 			ret = mdb_ctf_member_iter(id, offset_to_name_cb, &mbc);
    888 			if (ret == -1)
    889 				return (-1); /* errno is set for us */
    890 
    891 			/*
    892 			 * If we did not find a member containing this offset
    893 			 * (due to holes in the structure), return EINVAL.
    894 			 */
    895 			if (ret == 0)
    896 				return (set_errno(EINVAL));
    897 
    898 			break;
    899 		}
    900 
    901 		case CTF_K_UNION:
    902 			/*
    903 			 * Treat unions like atomic entities since we can't
    904 			 * do more than guess which member of the union
    905 			 * might be the intended one.
    906 			 */
    907 			goto done;
    908 
    909 		case CTF_K_INTEGER:
    910 		case CTF_K_FLOAT:
    911 		case CTF_K_POINTER:
    912 		case CTF_K_ENUM:
    913 			goto done;
    914 
    915 		default:
    916 			return (set_errno(EINVAL));
    917 		}
    918 
    919 		dot = 1;
    920 	}
    921 done:
    922 	if (midp != NULL)
    923 		*midp = id;
    924 	if (moffp != NULL)
    925 		*moffp = off;
    926 
    927 	return (mbc.mbc_total);
    928 }
    929 
    930 /*
    931  * Check if two types are structurally the same rather than logically
    932  * the same. That is to say that two types are equal if they have the
    933  * same logical structure rather than having the same ids in CTF-land.
    934  */
    935 static int type_equals(mdb_ctf_id_t, mdb_ctf_id_t);
    936 
    937 static int
    938 type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data)
    939 {
    940 	mdb_ctf_id_t b = *(mdb_ctf_id_t *)data;
    941 	ulong_t boff;
    942 	mdb_ctf_id_t bmem;
    943 
    944 	/*
    945 	 * Look up the corresponding member in the other composite type.
    946 	 */
    947 	if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0)
    948 		return (1);
    949 
    950 	/*
    951 	 * We don't allow members to be shuffled around.
    952 	 */
    953 	if (aoff != boff)
    954 		return (1);
    955 
    956 	return (type_equals(amem, bmem) ? 0 : 1);
    957 }
    958 
    959 static int
    960 type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b)
    961 {
    962 	size_t asz, bsz;
    963 	int akind, bkind;
    964 	mdb_ctf_arinfo_t aar, bar;
    965 
    966 	/*
    967 	 * Resolve both types down to their fundamental types, and make
    968 	 * sure their sizes and kinds match.
    969 	 */
    970 	if (mdb_ctf_type_resolve(a, &a) != 0 ||
    971 	    mdb_ctf_type_resolve(b, &b) != 0 ||
    972 	    (asz = mdb_ctf_type_size(a)) == -1UL ||
    973 	    (bsz = mdb_ctf_type_size(b)) == -1UL ||
    974 	    (akind = mdb_ctf_type_kind(a)) == -1 ||
    975 	    (bkind = mdb_ctf_type_kind(b)) == -1 ||
    976 	    asz != bsz || akind != bkind) {
    977 		return (0);
    978 	}
    979 
    980 	switch (akind) {
    981 	case CTF_K_INTEGER:
    982 	case CTF_K_FLOAT:
    983 	case CTF_K_POINTER:
    984 		/*
    985 		 * For pointers we could be a little stricter and require
    986 		 * both pointers to reference types which look vaguely
    987 		 * similar (for example, we could insist that the two types
    988 		 * have the same name). However, all we really care about
    989 		 * here is that the structure of the two types are the same,
    990 		 * and, in that regard, one pointer is as good as another.
    991 		 */
    992 		return (1);
    993 
    994 	case CTF_K_UNION:
    995 	case CTF_K_STRUCT:
    996 		/*
    997 		 * The test for the number of members is only strictly
    998 		 * necessary for unions since we'll find other problems with
    999 		 * structs. However, the extra check will do no harm.
   1000 		 */
   1001 		return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) &&
   1002 		    mdb_ctf_member_iter(a, type_equals_cb, &b) == 0);
   1003 
   1004 	case CTF_K_ARRAY:
   1005 		return (mdb_ctf_array_info(a, &aar) == 0 &&
   1006 		    mdb_ctf_array_info(b, &bar) == 0 &&
   1007 		    aar.mta_nelems == bar.mta_nelems &&
   1008 		    type_equals(aar.mta_index, bar.mta_index) &&
   1009 		    type_equals(aar.mta_contents, bar.mta_contents));
   1010 	}
   1011 
   1012 	return (0);
   1013 }
   1014 
   1015 
   1016 typedef struct member {
   1017 	char		*m_modbuf;
   1018 	char		*m_tgtbuf;
   1019 	mdb_ctf_id_t	m_tgtid;
   1020 	uint_t		m_flags;
   1021 } member_t;
   1022 
   1023 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *, uint_t);
   1024 
   1025 static int
   1026 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
   1027 {
   1028 	member_t *mp = data;
   1029 	char *modbuf = mp->m_modbuf;
   1030 	mdb_ctf_id_t tgtmid;
   1031 	char *tgtbuf = mp->m_tgtbuf;
   1032 	ulong_t tgtoff;
   1033 
   1034 	if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
   1035 		if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT)
   1036 			return (0);
   1037 		else
   1038 			return (set_errno(EMDB_CTFNOMEMB));
   1039 	}
   1040 
   1041 	return (vread_helper(modmid, modbuf + modoff / NBBY,
   1042 	    tgtmid, tgtbuf + tgtoff / NBBY, mp->m_flags));
   1043 }
   1044 
   1045 
   1046 static int
   1047 vread_helper(mdb_ctf_id_t modid, char *modbuf,
   1048     mdb_ctf_id_t tgtid, char *tgtbuf, uint_t flags)
   1049 {
   1050 	size_t modsz, tgtsz;
   1051 	int modkind, tgtkind;
   1052 	member_t mbr;
   1053 	int ret;
   1054 	mdb_ctf_arinfo_t tar, mar;
   1055 	int i;
   1056 
   1057 	/*
   1058 	 * Resolve the types to their canonical form.
   1059 	 */
   1060 	(void) mdb_ctf_type_resolve(modid, &modid);
   1061 	(void) mdb_ctf_type_resolve(tgtid, &tgtid);
   1062 
   1063 	if ((modkind = mdb_ctf_type_kind(modid)) == -1)
   1064 		return (-1); /* errno is set for us */
   1065 	if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1)
   1066 		return (-1); /* errno is set for us */
   1067 
   1068 	if (tgtkind != modkind)
   1069 		return (set_errno(EMDB_INCOMPAT));
   1070 
   1071 	switch (modkind) {
   1072 	case CTF_K_INTEGER:
   1073 	case CTF_K_FLOAT:
   1074 	case CTF_K_POINTER:
   1075 		if ((modsz = mdb_ctf_type_size(modid)) == -1UL)
   1076 			return (-1); /* errno is set for us */
   1077 
   1078 		if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL)
   1079 			return (-1); /* errno is set for us */
   1080 
   1081 		/*
   1082 		 * If the sizes don't match we need to be tricky to make
   1083 		 * sure that the caller gets the correct data.
   1084 		 */
   1085 		if (modsz < tgtsz) {
   1086 			if (!(flags & MDB_CTF_VREAD_IGNORE_GROW))
   1087 				return (set_errno(EMDB_INCOMPAT));
   1088 #ifdef _BIG_ENDIAN
   1089 			bcopy(tgtbuf + tgtsz - modsz, modbuf, modsz);
   1090 #else
   1091 			bcopy(tgtbuf, modbuf, modsz);
   1092 #endif
   1093 		} else if (modsz > tgtsz) {
   1094 			bzero(modbuf, modsz);
   1095 #ifdef _BIG_ENDIAN
   1096 			bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz);
   1097 #else
   1098 			bcopy(tgtbuf, modbuf, tgtsz);
   1099 #endif
   1100 		} else {
   1101 			bcopy(tgtbuf, modbuf, modsz);
   1102 		}
   1103 
   1104 		return (0);
   1105 
   1106 	case CTF_K_STRUCT:
   1107 		mbr.m_modbuf = modbuf;
   1108 		mbr.m_tgtbuf = tgtbuf;
   1109 		mbr.m_tgtid = tgtid;
   1110 		mbr.m_flags = flags;
   1111 
   1112 		return (mdb_ctf_member_iter(modid, member_cb, &mbr));
   1113 
   1114 	case CTF_K_UNION:
   1115 
   1116 		/*
   1117 		 * Unions are a little tricky. The only time it's truly
   1118 		 * safe to read in a union is if no part of the union or
   1119 		 * any of its component types have changed. We allow the
   1120 		 * consumer to ignore unions. The correct use of this
   1121 		 * feature is to read the containing structure, figure
   1122 		 * out which component of the union is valid, compute
   1123 		 * the location of that in the target and then read in
   1124 		 * that part of the structure.
   1125 		 */
   1126 		if (flags & MDB_CTF_VREAD_IGNORE_UNIONS)
   1127 			return (0);
   1128 
   1129 		if (!type_equals(modid, tgtid))
   1130 			return (set_errno(EMDB_INCOMPAT));
   1131 
   1132 		modsz = mdb_ctf_type_size(modid);
   1133 		tgtsz = mdb_ctf_type_size(tgtid);
   1134 
   1135 		ASSERT(modsz == tgtsz);
   1136 
   1137 		bcopy(tgtbuf, modbuf, modsz);
   1138 
   1139 		return (0);
   1140 
   1141 	case CTF_K_ARRAY:
   1142 		if (mdb_ctf_array_info(tgtid, &tar) != 0)
   1143 			return (-1); /* errno is set for us */
   1144 		if (mdb_ctf_array_info(modid, &mar) != 0)
   1145 			return (-1); /* errno is set for us */
   1146 
   1147 		if (tar.mta_nelems != mar.mta_nelems)
   1148 			return (set_errno(EMDB_INCOMPAT));
   1149 
   1150 		if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL)
   1151 			return (-1); /* errno is set for us */
   1152 
   1153 		if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL)
   1154 			return (-1); /* errno is set for us */
   1155 
   1156 		for (i = 0; i < tar.mta_nelems; i++) {
   1157 			ret = vread_helper(mar.mta_contents, modbuf + i * modsz,
   1158 			    tar.mta_contents, tgtbuf + i * tgtsz, flags);
   1159 
   1160 			if (ret != 0)
   1161 				return (ret);
   1162 		}
   1163 
   1164 		return (0);
   1165 	}
   1166 
   1167 	return (set_errno(EMDB_INCOMPAT));
   1168 }
   1169 
   1170 
   1171 int
   1172 mdb_ctf_vread(void *modbuf, const char *typename, uintptr_t addr, uint_t flags)
   1173 {
   1174 	ctf_file_t *mfp;
   1175 	ctf_id_t mid;
   1176 	void *tgtbuf;
   1177 	size_t size;
   1178 	mdb_ctf_id_t tgtid;
   1179 	mdb_ctf_id_t modid;
   1180 	mdb_module_t *mod;
   1181 
   1182 	if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL)
   1183 		return (set_errno(EMDB_NOCTF));
   1184 
   1185 	if ((mid = ctf_lookup_by_name(mfp, typename)) == CTF_ERR) {
   1186 		mdb_dprintf(MDB_DBG_CTF, "couldn't find module's ctf data\n");
   1187 		return (set_errno(ctf_to_errno(ctf_errno(mfp))));
   1188 	}
   1189 
   1190 	set_ctf_id(&modid, mfp, mid);
   1191 
   1192 	if (mdb_ctf_lookup_by_name(typename, &tgtid) != 0) {
   1193 		mdb_dprintf(MDB_DBG_CTF, "couldn't find target's ctf data\n");
   1194 		return (set_errno(EMDB_NOCTF));
   1195 	}
   1196 
   1197 	/*
   1198 	 * Read the data out of the target's address space.
   1199 	 */
   1200 	if ((size = mdb_ctf_type_size(tgtid)) == -1UL)
   1201 		return (-1); /* errno is set for us */
   1202 
   1203 	tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
   1204 
   1205 	if (mdb_vread(tgtbuf, size, addr) < 0)
   1206 		return (-1); /* errno is set for us */
   1207 
   1208 	return (vread_helper(modid, modbuf, tgtid, tgtbuf, flags));
   1209 }
   1210 
   1211 int
   1212 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
   1213 {
   1214 	GElf_Sym sym;
   1215 
   1216 	if (mdb_lookup_by_name(name, &sym) != 0)
   1217 		return (-1); /* errno is set for us */
   1218 
   1219 	return (mdb_ctf_vread(buf, typename, sym.st_value, flags));
   1220 }
   1221 
   1222 ctf_file_t *
   1223 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va,
   1224     Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp)
   1225 {
   1226 	ctf_sect_t ctdata, symtab, strtab;
   1227 
   1228 	ctdata.cts_name = ".SUNW_ctf";
   1229 	ctdata.cts_type = SHT_PROGBITS;
   1230 	ctdata.cts_flags = 0;
   1231 	ctdata.cts_data = ctf_va;
   1232 	ctdata.cts_size = ctf_size;
   1233 	ctdata.cts_entsize = 1;
   1234 	ctdata.cts_offset = 0;
   1235 
   1236 	symtab.cts_name = ".symtab";
   1237 	symtab.cts_type = symhdr->sh_type;
   1238 	symtab.cts_flags = symhdr->sh_flags;
   1239 	symtab.cts_data = sym_va;
   1240 	symtab.cts_size = symhdr->sh_size;
   1241 	symtab.cts_entsize = symhdr->sh_entsize;
   1242 	symtab.cts_offset = symhdr->sh_offset;
   1243 
   1244 	strtab.cts_name = ".strtab";
   1245 	strtab.cts_type = strhdr->sh_type;
   1246 	strtab.cts_flags = strhdr->sh_flags;
   1247 	strtab.cts_data = str_va;
   1248 	strtab.cts_size = strhdr->sh_size;
   1249 	strtab.cts_entsize = strhdr->sh_entsize;
   1250 	strtab.cts_offset = strhdr->sh_offset;
   1251 
   1252 	return (ctf_bufopen(&ctdata, &symtab, &strtab, errp));
   1253 }
   1254