xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_ctf.c (revision 22ce014825a14b6ce90123db2834a13e343d6caf)
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  * Copyright (c) 2013 by Delphix. All rights reserved.
27  */
28 
29 #include <mdb/mdb_ctf.h>
30 #include <mdb/mdb_ctf_impl.h>
31 #include <mdb/mdb_err.h>
32 #include <mdb/mdb_modapi.h>
33 #include <mdb/mdb_string.h>
34 #include <mdb/mdb.h>
35 #include <mdb/mdb_debug.h>
36 
37 #include <libctf.h>
38 #include <string.h>
39 
40 typedef struct tnarg {
41 	mdb_tgt_t *tn_tgt;		/* target to use for lookup */
42 	const char *tn_name;		/* query string to lookup */
43 	ctf_file_t *tn_fp;		/* CTF container from match */
44 	ctf_id_t tn_id;			/* CTF type ID from match */
45 } tnarg_t;
46 
47 typedef struct type_iter {
48 	mdb_ctf_type_f *ti_cb;
49 	void *ti_arg;
50 	ctf_file_t *ti_fp;
51 } type_iter_t;
52 
53 typedef struct member_iter {
54 	mdb_ctf_member_f *mi_cb;
55 	void *mi_arg;
56 	ctf_file_t *mi_fp;
57 } member_iter_t;
58 
59 typedef struct type_visit {
60 	mdb_ctf_visit_f	*tv_cb;
61 	void		*tv_arg;
62 	ctf_file_t	*tv_fp;
63 	ulong_t		tv_base_offset;	/* used when recursing from type_cb() */
64 	int		tv_base_depth;	/* used when recursing from type_cb() */
65 	int		tv_min_depth;
66 } type_visit_t;
67 
68 typedef struct mbr_info {
69 	const char *mbr_member;
70 	ulong_t *mbr_offp;
71 	mdb_ctf_id_t *mbr_typep;
72 } mbr_info_t;
73 
74 static void
75 set_ctf_id(mdb_ctf_id_t *p, ctf_file_t *fp, ctf_id_t id)
76 {
77 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
78 
79 	mcip->mci_fp = fp;
80 	mcip->mci_id = id;
81 }
82 
83 /*
84  * Callback function for mdb_tgt_object_iter used from name_to_type, below,
85  * to search the CTF namespace of each object file for a particular name.
86  */
87 /*ARGSUSED*/
88 static int
89 obj_lookup(void *data, const mdb_map_t *mp, const char *name)
90 {
91 	tnarg_t *tnp = data;
92 	ctf_file_t *fp;
93 	ctf_id_t id;
94 
95 	if ((fp = mdb_tgt_name_to_ctf(tnp->tn_tgt, name)) != NULL &&
96 	    (id = ctf_lookup_by_name(fp, tnp->tn_name)) != CTF_ERR) {
97 		tnp->tn_fp = fp;
98 		tnp->tn_id = id;
99 
100 		/*
101 		 * We may have found a forward declaration.  If we did, we'll
102 		 * note the ID and file pointer, but we'll keep searching in
103 		 * an attempt to find the real thing.  If we found something
104 		 * real (i.e. not a forward), we stop the iteration.
105 		 */
106 		return (ctf_type_kind(fp, id) == CTF_K_FORWARD ? 0 : -1);
107 	}
108 
109 	return (0);
110 }
111 
112 /*
113  * Convert a string type name with an optional leading object specifier into
114  * the corresponding CTF file container and type ID.  If an error occurs, we
115  * print an appropriate message and return NULL.
116  */
117 static ctf_file_t *
118 name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp)
119 {
120 	const char *object = MDB_TGT_OBJ_EXEC;
121 	ctf_file_t *fp = NULL;
122 	ctf_id_t id;
123 	tnarg_t arg;
124 	char *p, *s;
125 	char buf[MDB_SYM_NAMLEN];
126 	char *name = &buf[0];
127 
128 	(void) mdb_snprintf(buf, sizeof (buf), "%s", cname);
129 
130 	if ((p = strrsplit(name, '`')) != NULL) {
131 		/*
132 		 * We need to shuffle things around a little to support
133 		 * type names of the form "struct module`name".
134 		 */
135 		if ((s = strsplit(name, ' ')) != NULL) {
136 			bcopy(cname + (s - name), name, (p - s) - 1);
137 			name[(p - s) - 1] = '\0';
138 			bcopy(cname, name + (p - s), s - name);
139 			p = name + (p - s);
140 		}
141 		if (*name != '\0')
142 			object = name;
143 		name = p;
144 	}
145 
146 	/*
147 	 * Attempt to look up the name in the primary object file.  If this
148 	 * fails and the name was unscoped, search all remaining object files.
149 	 */
150 	if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL ||
151 	    (id = ctf_lookup_by_name(fp, name)) == CTF_ERR ||
152 	    ctf_type_kind(fp, id) == CTF_K_FORWARD) &&
153 	    object == MDB_TGT_OBJ_EXEC) {
154 
155 		arg.tn_tgt = t;
156 		arg.tn_name = name;
157 		arg.tn_fp = NULL;
158 		arg.tn_id = CTF_ERR;
159 
160 		(void) mdb_tgt_object_iter(t, obj_lookup, &arg);
161 
162 		if (arg.tn_id != CTF_ERR) {
163 			fp = arg.tn_fp;
164 			id = arg.tn_id;
165 		}
166 	}
167 
168 	if (fp == NULL)
169 		return (NULL); /* errno is set for us */
170 
171 	if (id == CTF_ERR) {
172 		(void) set_errno(ctf_to_errno(ctf_errno(fp)));
173 		return (NULL);
174 	}
175 
176 	*idp = id;
177 	return (fp);
178 }
179 
180 /*
181  * Check to see if there is ctf data in the given object. This is useful
182  * so that we don't enter some loop where every call to lookup fails.
183  */
184 int
185 mdb_ctf_enabled_by_object(const char *object)
186 {
187 	mdb_tgt_t *t = mdb.m_target;
188 
189 	return (mdb_tgt_name_to_ctf(t, object) != NULL);
190 }
191 
192 int
193 mdb_ctf_lookup_by_name(const char *name, mdb_ctf_id_t *p)
194 {
195 	ctf_file_t *fp = NULL;
196 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
197 	mdb_tgt_t *t = mdb.m_target;
198 
199 	if (mcip == NULL)
200 		return (set_errno(EINVAL));
201 
202 	if ((fp = name_to_type(t, name, &mcip->mci_id)) == NULL) {
203 		mdb_ctf_type_invalidate(p);
204 		return (-1); /* errno is set for us */
205 	}
206 
207 	mcip->mci_fp = fp;
208 
209 	return (0);
210 }
211 
212 int
213 mdb_ctf_lookup_by_symbol(const GElf_Sym *symp, const mdb_syminfo_t *sip,
214     mdb_ctf_id_t *p)
215 {
216 	ctf_file_t *fp = NULL;
217 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
218 	mdb_tgt_t *t = mdb.m_target;
219 
220 	if (mcip == NULL)
221 		return (set_errno(EINVAL));
222 
223 	if (symp == NULL || sip == NULL) {
224 		mdb_ctf_type_invalidate(p);
225 		return (set_errno(EINVAL));
226 	}
227 
228 	if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL) {
229 		mdb_ctf_type_invalidate(p);
230 		return (-1); /* errno is set for us */
231 	}
232 
233 	if ((mcip->mci_id = ctf_lookup_by_symbol(fp, sip->sym_id)) == CTF_ERR) {
234 		mdb_ctf_type_invalidate(p);
235 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
236 	}
237 
238 	mcip->mci_fp = fp;
239 
240 	return (0);
241 }
242 
243 int
244 mdb_ctf_lookup_by_addr(uintptr_t addr, mdb_ctf_id_t *p)
245 {
246 	GElf_Sym sym;
247 	mdb_syminfo_t si;
248 	char name[MDB_SYM_NAMLEN];
249 	const mdb_map_t *mp;
250 	mdb_tgt_t *t = mdb.m_target;
251 	const char *obj, *c;
252 
253 	if (p == NULL)
254 		return (set_errno(EINVAL));
255 
256 	if (mdb_tgt_lookup_by_addr(t, addr, MDB_TGT_SYM_EXACT, name,
257 	    sizeof (name), NULL, NULL) == -1) {
258 		mdb_ctf_type_invalidate(p);
259 		return (-1); /* errno is set for us */
260 	}
261 
262 	if ((c = strrsplit(name, '`')) != NULL) {
263 		obj = name;
264 	} else {
265 		if ((mp = mdb_tgt_addr_to_map(t, addr)) == NULL) {
266 			mdb_ctf_type_invalidate(p);
267 			return (-1); /* errno is set for us */
268 		}
269 
270 		obj = mp->map_name;
271 		c = name;
272 	}
273 
274 	if (mdb_tgt_lookup_by_name(t, obj, c, &sym, &si) == -1) {
275 		mdb_ctf_type_invalidate(p);
276 		return (-1); /* errno is set for us */
277 	}
278 
279 	return (mdb_ctf_lookup_by_symbol(&sym, &si, p));
280 }
281 
282 int
283 mdb_ctf_module_lookup(const char *name, mdb_ctf_id_t *p)
284 {
285 	ctf_file_t *fp;
286 	ctf_id_t id;
287 	mdb_module_t *mod;
288 
289 	if ((mod = mdb_get_module()) == NULL)
290 		return (set_errno(EMDB_CTX));
291 
292 	if ((fp = mod->mod_ctfp) == NULL)
293 		return (set_errno(EMDB_NOCTF));
294 
295 	if ((id = ctf_lookup_by_name(fp, name)) == CTF_ERR)
296 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
297 
298 	set_ctf_id(p, fp, id);
299 
300 	return (0);
301 }
302 
303 /*ARGSUSED*/
304 int
305 mdb_ctf_func_info(const GElf_Sym *symp, const mdb_syminfo_t *sip,
306     mdb_ctf_funcinfo_t *mfp)
307 {
308 	ctf_file_t *fp = NULL;
309 	ctf_funcinfo_t f;
310 	mdb_tgt_t *t = mdb.m_target;
311 	char name[MDB_SYM_NAMLEN];
312 	const mdb_map_t *mp;
313 	mdb_syminfo_t si;
314 	int err;
315 
316 	if (symp == NULL || mfp == NULL)
317 		return (set_errno(EINVAL));
318 
319 	/*
320 	 * In case the input symbol came from a merged or private symbol table,
321 	 * re-lookup the address as a symbol, and then perform a fully scoped
322 	 * lookup of that symbol name to get the mdb_syminfo_t for its CTF.
323 	 */
324 	if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL ||
325 	    (mp = mdb_tgt_addr_to_map(t, symp->st_value)) == NULL ||
326 	    mdb_tgt_lookup_by_addr(t, symp->st_value, MDB_TGT_SYM_FUZZY,
327 	    name, sizeof (name), NULL, NULL) != 0)
328 		return (-1); /* errno is set for us */
329 
330 	if (strchr(name, '`') != NULL)
331 		err = mdb_tgt_lookup_by_scope(t, name, NULL, &si);
332 	else
333 		err = mdb_tgt_lookup_by_name(t, mp->map_name, name, NULL, &si);
334 
335 	if (err != 0)
336 		return (-1); /* errno is set for us */
337 
338 	if (ctf_func_info(fp, si.sym_id, &f) == CTF_ERR)
339 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
340 
341 	set_ctf_id(&mfp->mtf_return, fp, f.ctc_return);
342 	mfp->mtf_argc = f.ctc_argc;
343 	mfp->mtf_flags = f.ctc_flags;
344 	mfp->mtf_symidx = si.sym_id;
345 
346 	return (0);
347 }
348 
349 int
350 mdb_ctf_func_args(const mdb_ctf_funcinfo_t *funcp, uint_t len,
351     mdb_ctf_id_t *argv)
352 {
353 	ctf_file_t *fp;
354 	ctf_id_t cargv[32];
355 	int i;
356 
357 	if (len > (sizeof (cargv) / sizeof (cargv[0])))
358 		return (set_errno(EINVAL));
359 
360 	if (funcp == NULL || argv == NULL)
361 		return (set_errno(EINVAL));
362 
363 	fp = mdb_ctf_type_file(funcp->mtf_return);
364 
365 	if (ctf_func_args(fp, funcp->mtf_symidx, len, cargv) == CTF_ERR)
366 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
367 
368 	for (i = MIN(len, funcp->mtf_argc) - 1; i >= 0; i--) {
369 		set_ctf_id(&argv[i], fp, cargv[i]);
370 	}
371 
372 	return (0);
373 }
374 
375 void
376 mdb_ctf_type_invalidate(mdb_ctf_id_t *idp)
377 {
378 	set_ctf_id(idp, NULL, CTF_ERR);
379 }
380 
381 int
382 mdb_ctf_type_valid(mdb_ctf_id_t id)
383 {
384 	return (((mdb_ctf_impl_t *)&id)->mci_id != CTF_ERR);
385 }
386 
387 int
388 mdb_ctf_type_cmp(mdb_ctf_id_t aid, mdb_ctf_id_t bid)
389 {
390 	mdb_ctf_impl_t *aidp = (mdb_ctf_impl_t *)&aid;
391 	mdb_ctf_impl_t *bidp = (mdb_ctf_impl_t *)&bid;
392 
393 	return (ctf_type_cmp(aidp->mci_fp, aidp->mci_id,
394 	    bidp->mci_fp, bidp->mci_id));
395 }
396 
397 int
398 mdb_ctf_type_resolve(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
399 {
400 	ctf_id_t id;
401 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&mid;
402 
403 	if ((id = ctf_type_resolve(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
404 		if (outp)
405 			mdb_ctf_type_invalidate(outp);
406 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
407 	}
408 
409 	if (ctf_type_kind(idp->mci_fp, id) == CTF_K_FORWARD) {
410 		char name[MDB_SYM_NAMLEN];
411 		mdb_ctf_id_t lookup_id;
412 
413 		if (ctf_type_name(idp->mci_fp, id, name, sizeof (name)) !=
414 		    NULL &&
415 		    mdb_ctf_lookup_by_name(name, &lookup_id) == 0 &&
416 		    outp != NULL) {
417 			*outp = lookup_id;
418 			return (0);
419 		}
420 	}
421 
422 	if (outp != NULL)
423 		set_ctf_id(outp, idp->mci_fp, id);
424 
425 	return (0);
426 }
427 
428 char *
429 mdb_ctf_type_name(mdb_ctf_id_t id, char *buf, size_t len)
430 {
431 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
432 	char *ret;
433 
434 	if (!mdb_ctf_type_valid(id)) {
435 		(void) set_errno(EINVAL);
436 		return (NULL);
437 	}
438 
439 	ret = ctf_type_name(idp->mci_fp, idp->mci_id, buf, len);
440 	if (ret == NULL)
441 		(void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
442 
443 	return (ret);
444 }
445 
446 ssize_t
447 mdb_ctf_type_size(mdb_ctf_id_t id)
448 {
449 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
450 	ssize_t ret;
451 
452 	/* resolve the type in case there's a forward declaration */
453 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
454 		return (ret);
455 
456 	if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR)
457 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
458 
459 	return (ret);
460 }
461 
462 int
463 mdb_ctf_type_kind(mdb_ctf_id_t id)
464 {
465 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
466 	int ret;
467 
468 	if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR)
469 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
470 
471 	return (ret);
472 }
473 
474 int
475 mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
476 {
477 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&mid;
478 	ctf_id_t id;
479 
480 	if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
481 		if (outp)
482 			mdb_ctf_type_invalidate(outp);
483 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
484 	}
485 
486 	if (outp != NULL)
487 		set_ctf_id(outp, idp->mci_fp, id);
488 
489 	return (0);
490 }
491 
492 
493 int
494 mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep)
495 {
496 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
497 
498 	if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR)
499 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
500 
501 	return (0);
502 }
503 
504 /*
505  * callback proxy for mdb_ctf_type_visit
506  */
507 static int
508 type_cb(const char *name, ctf_id_t type, ulong_t off, int depth, void *arg)
509 {
510 	type_visit_t *tvp = arg;
511 	mdb_ctf_id_t id;
512 	mdb_ctf_id_t base;
513 	mdb_ctf_impl_t *basep = (mdb_ctf_impl_t *)&base;
514 
515 	int ret;
516 
517 	if (depth < tvp->tv_min_depth)
518 		return (0);
519 
520 	off += tvp->tv_base_offset;
521 	depth += tvp->tv_base_depth;
522 
523 	set_ctf_id(&id, tvp->tv_fp, type);
524 
525 	(void) mdb_ctf_type_resolve(id, &base);
526 	if ((ret = tvp->tv_cb(name, id, base, off, depth, tvp->tv_arg)) != 0)
527 		return (ret);
528 
529 	/*
530 	 * If the type resolves to a type in a different file, we must have
531 	 * followed a forward declaration.  We need to recurse into the
532 	 * new type.
533 	 */
534 	if (basep->mci_fp != tvp->tv_fp && mdb_ctf_type_valid(base)) {
535 		type_visit_t tv;
536 
537 		tv.tv_cb = tvp->tv_cb;
538 		tv.tv_arg = tvp->tv_arg;
539 		tv.tv_fp = basep->mci_fp;
540 
541 		tv.tv_base_offset = off;
542 		tv.tv_base_depth = depth;
543 		tv.tv_min_depth = 1;	/* depth = 0 has already been done */
544 
545 		ret = ctf_type_visit(basep->mci_fp, basep->mci_id,
546 		    type_cb, &tv);
547 	}
548 	return (ret);
549 }
550 
551 int
552 mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg)
553 {
554 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
555 	type_visit_t tv;
556 	int ret;
557 
558 	tv.tv_cb = func;
559 	tv.tv_arg = arg;
560 	tv.tv_fp = idp->mci_fp;
561 	tv.tv_base_offset = 0;
562 	tv.tv_base_depth = 0;
563 	tv.tv_min_depth = 0;
564 
565 	ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv);
566 
567 	if (ret == CTF_ERR)
568 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
569 
570 	return (ret);
571 }
572 
573 int
574 mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp)
575 {
576 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
577 	ctf_arinfo_t car;
578 
579 	if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR)
580 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
581 
582 	set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents);
583 	set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index);
584 
585 	arp->mta_nelems = car.ctr_nelems;
586 
587 	return (0);
588 }
589 
590 const char *
591 mdb_ctf_enum_name(mdb_ctf_id_t id, int value)
592 {
593 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
594 	const char *ret;
595 
596 	/* resolve the type in case there's a forward declaration */
597 	if (mdb_ctf_type_resolve(id, &id) != 0)
598 		return (NULL);
599 
600 	if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL)
601 		(void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
602 
603 	return (ret);
604 }
605 
606 /*
607  * callback proxy for mdb_ctf_member_iter
608  */
609 static int
610 member_iter_cb(const char *name, ctf_id_t type, ulong_t off, void *data)
611 {
612 	member_iter_t *mip = data;
613 	mdb_ctf_id_t id;
614 
615 	set_ctf_id(&id, mip->mi_fp, type);
616 
617 	return (mip->mi_cb(name, id, off, mip->mi_arg));
618 }
619 
620 int
621 mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data)
622 {
623 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
624 	member_iter_t mi;
625 	int ret;
626 
627 	/* resolve the type in case there's a forward declaration */
628 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
629 		return (ret);
630 
631 	mi.mi_cb = cb;
632 	mi.mi_arg = data;
633 	mi.mi_fp = idp->mci_fp;
634 
635 	ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi);
636 
637 	if (ret == CTF_ERR)
638 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
639 
640 	return (ret);
641 }
642 
643 int
644 mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data)
645 {
646 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
647 	int ret;
648 
649 	/* resolve the type in case there's a forward declaration */
650 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
651 		return (ret);
652 
653 	return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data));
654 }
655 
656 /*
657  * callback proxy for mdb_ctf_type_iter
658  */
659 static int
660 type_iter_cb(ctf_id_t type, void *data)
661 {
662 	type_iter_t *tip = data;
663 	mdb_ctf_id_t id;
664 
665 	set_ctf_id(&id, tip->ti_fp, type);
666 
667 	return (tip->ti_cb(id, tip->ti_arg));
668 }
669 
670 int
671 mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data)
672 {
673 	ctf_file_t *fp;
674 	mdb_tgt_t *t = mdb.m_target;
675 	int ret;
676 	type_iter_t ti;
677 
678 	if ((fp = mdb_tgt_name_to_ctf(t, object)) == NULL)
679 		return (-1);
680 
681 	ti.ti_cb = cb;
682 	ti.ti_arg = data;
683 	ti.ti_fp = fp;
684 
685 	if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR)
686 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
687 
688 	return (ret);
689 }
690 
691 /* utility functions */
692 
693 ctf_id_t
694 mdb_ctf_type_id(mdb_ctf_id_t id)
695 {
696 	return (((mdb_ctf_impl_t *)&id)->mci_id);
697 }
698 
699 ctf_file_t *
700 mdb_ctf_type_file(mdb_ctf_id_t id)
701 {
702 	return (((mdb_ctf_impl_t *)&id)->mci_fp);
703 }
704 
705 static int
706 member_info_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
707 {
708 	mbr_info_t *mbrp = data;
709 
710 	if (strcmp(name, mbrp->mbr_member) == 0) {
711 		if (mbrp->mbr_offp != NULL)
712 			*(mbrp->mbr_offp) = off;
713 		if (mbrp->mbr_typep != NULL)
714 			*(mbrp->mbr_typep) = id;
715 
716 		return (1);
717 	}
718 
719 	return (0);
720 }
721 
722 int
723 mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp,
724     mdb_ctf_id_t *typep)
725 {
726 	mbr_info_t mbr;
727 	int rc;
728 
729 	mbr.mbr_member = member;
730 	mbr.mbr_offp = offp;
731 	mbr.mbr_typep = typep;
732 
733 	rc = mdb_ctf_member_iter(id, member_info_cb, &mbr);
734 
735 	/* couldn't get member list */
736 	if (rc == -1)
737 		return (-1); /* errno is set for us */
738 
739 	/* not a member */
740 	if (rc == 0)
741 		return (set_errno(EMDB_CTFNOMEMB));
742 
743 	return (0);
744 }
745 
746 /*
747  * Returns offset in _bits_ in *retp.
748  */
749 int
750 mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp)
751 {
752 	return (mdb_ctf_member_info(id, member, retp, NULL));
753 }
754 
755 /*
756  * Returns offset in _bytes_, or -1 on failure.
757  */
758 int
759 mdb_ctf_offsetof_by_name(const char *type, const char *member)
760 {
761 	mdb_ctf_id_t id;
762 	ulong_t off;
763 
764 	if (mdb_ctf_lookup_by_name(type, &id) == -1) {
765 		mdb_warn("couldn't find type %s", type);
766 		return (-1);
767 	}
768 
769 	if (mdb_ctf_offsetof(id, member, &off) == -1) {
770 		mdb_warn("couldn't find member %s of type %s", member, type);
771 		return (-1);
772 	}
773 	if (off % 8 != 0) {
774 		mdb_warn("member %s of type %s is an unsupported bitfield\n",
775 		    member, type);
776 		return (-1);
777 	}
778 	off /= 8;
779 
780 	return (off);
781 }
782 
783 
784 /*ARGSUSED*/
785 static int
786 num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
787 {
788 	int *count = data;
789 	*count = *count + 1;
790 	return (0);
791 }
792 
793 int
794 mdb_ctf_num_members(mdb_ctf_id_t id)
795 {
796 	int count = 0;
797 
798 	if (mdb_ctf_member_iter(id, num_members_cb, &count) != 0)
799 		return (-1); /* errno is set for us */
800 
801 	return (count);
802 }
803 
804 typedef struct mbr_contains {
805 	char **mbc_bufp;
806 	size_t *mbc_lenp;
807 	ulong_t *mbc_offp;
808 	mdb_ctf_id_t *mbc_idp;
809 	ssize_t mbc_total;
810 } mbr_contains_t;
811 
812 static int
813 offset_to_name_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
814 {
815 	mbr_contains_t *mbc = data;
816 	ulong_t size;
817 	ctf_encoding_t e;
818 	size_t n;
819 
820 	if (*mbc->mbc_offp < off)
821 		return (0);
822 
823 	if (mdb_ctf_type_encoding(id, &e) == -1)
824 		size = mdb_ctf_type_size(id) * NBBY;
825 	else
826 		size = e.cte_bits;
827 
828 	if (off + size <= *mbc->mbc_offp)
829 		return (0);
830 
831 	n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "%s", name);
832 	mbc->mbc_total += n;
833 	if (n > *mbc->mbc_lenp)
834 		n = *mbc->mbc_lenp;
835 
836 	*mbc->mbc_lenp -= n;
837 	*mbc->mbc_bufp += n;
838 
839 	*mbc->mbc_offp -= off;
840 	*mbc->mbc_idp = id;
841 
842 	return (1);
843 }
844 
845 ssize_t
846 mdb_ctf_offset_to_name(mdb_ctf_id_t id, ulong_t off, char *buf, size_t len,
847     int dot, mdb_ctf_id_t *midp, ulong_t *moffp)
848 {
849 	size_t size;
850 	size_t n;
851 	mbr_contains_t mbc;
852 
853 	if (!mdb_ctf_type_valid(id))
854 		return (set_errno(EINVAL));
855 
856 	/*
857 	 * Quick sanity check to make sure the given offset is within
858 	 * this scope of this type.
859 	 */
860 	if (mdb_ctf_type_size(id) * NBBY <= off)
861 		return (set_errno(EINVAL));
862 
863 	mbc.mbc_bufp = &buf;
864 	mbc.mbc_lenp = &len;
865 	mbc.mbc_offp = &off;
866 	mbc.mbc_idp = &id;
867 	mbc.mbc_total = 0;
868 
869 	*buf = '\0';
870 
871 	for (;;) {
872 		/*
873 		 * Check for an exact match.
874 		 */
875 		if (off == 0)
876 			break;
877 
878 		(void) mdb_ctf_type_resolve(id, &id);
879 
880 		/*
881 		 * Find the member that contains this offset.
882 		 */
883 		switch (mdb_ctf_type_kind(id)) {
884 		case CTF_K_ARRAY: {
885 			mdb_ctf_arinfo_t ar;
886 			uint_t index;
887 
888 			(void) mdb_ctf_array_info(id, &ar);
889 			size = mdb_ctf_type_size(ar.mta_contents) * NBBY;
890 			index = off / size;
891 
892 			id = ar.mta_contents;
893 			off %= size;
894 
895 			n = mdb_snprintf(buf, len, "[%u]", index);
896 			mbc.mbc_total += n;
897 			if (n > len)
898 				n = len;
899 
900 			buf += n;
901 			len -= n;
902 			break;
903 		}
904 
905 		case CTF_K_STRUCT: {
906 			int ret;
907 
908 			/*
909 			 * Find the member that contains this offset
910 			 * and continue.
911 			 */
912 
913 			if (dot) {
914 				mbc.mbc_total++;
915 				if (len != 0) {
916 					*buf++ = '.';
917 					*buf = '\0';
918 					len--;
919 				}
920 			}
921 
922 			ret = mdb_ctf_member_iter(id, offset_to_name_cb, &mbc);
923 			if (ret == -1)
924 				return (-1); /* errno is set for us */
925 
926 			/*
927 			 * If we did not find a member containing this offset
928 			 * (due to holes in the structure), return EINVAL.
929 			 */
930 			if (ret == 0)
931 				return (set_errno(EINVAL));
932 
933 			break;
934 		}
935 
936 		case CTF_K_UNION:
937 			/*
938 			 * Treat unions like atomic entities since we can't
939 			 * do more than guess which member of the union
940 			 * might be the intended one.
941 			 */
942 			goto done;
943 
944 		case CTF_K_INTEGER:
945 		case CTF_K_FLOAT:
946 		case CTF_K_POINTER:
947 		case CTF_K_ENUM:
948 			goto done;
949 
950 		default:
951 			return (set_errno(EINVAL));
952 		}
953 
954 		dot = 1;
955 	}
956 done:
957 	if (midp != NULL)
958 		*midp = id;
959 	if (moffp != NULL)
960 		*moffp = off;
961 
962 	return (mbc.mbc_total);
963 }
964 
965 static void
966 mdb_ctf_warn(uint_t flags, const char *format, ...)
967 {
968 	va_list alist;
969 
970 	if (flags & MDB_CTF_VREAD_QUIET)
971 		return;
972 
973 	va_start(alist, format);
974 	vwarn(format, alist);
975 	va_end(alist);
976 }
977 
978 /*
979  * Check if two types are structurally the same rather than logically
980  * the same. That is to say that two types are equal if they have the
981  * same logical structure rather than having the same ids in CTF-land.
982  */
983 static int type_equals(mdb_ctf_id_t, mdb_ctf_id_t);
984 
985 static int
986 type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data)
987 {
988 	mdb_ctf_id_t b = *(mdb_ctf_id_t *)data;
989 	ulong_t boff;
990 	mdb_ctf_id_t bmem;
991 
992 	/*
993 	 * Look up the corresponding member in the other composite type.
994 	 */
995 	if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0)
996 		return (1);
997 
998 	/*
999 	 * We don't allow members to be shuffled around.
1000 	 */
1001 	if (aoff != boff)
1002 		return (1);
1003 
1004 	return (type_equals(amem, bmem) ? 0 : 1);
1005 }
1006 
1007 static int
1008 type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b)
1009 {
1010 	size_t asz, bsz;
1011 	int akind, bkind;
1012 	mdb_ctf_arinfo_t aar, bar;
1013 
1014 	/*
1015 	 * Resolve both types down to their fundamental types, and make
1016 	 * sure their sizes and kinds match.
1017 	 */
1018 	if (mdb_ctf_type_resolve(a, &a) != 0 ||
1019 	    mdb_ctf_type_resolve(b, &b) != 0 ||
1020 	    (asz = mdb_ctf_type_size(a)) == -1UL ||
1021 	    (bsz = mdb_ctf_type_size(b)) == -1UL ||
1022 	    (akind = mdb_ctf_type_kind(a)) == -1 ||
1023 	    (bkind = mdb_ctf_type_kind(b)) == -1 ||
1024 	    asz != bsz || akind != bkind) {
1025 		return (0);
1026 	}
1027 
1028 	switch (akind) {
1029 	case CTF_K_INTEGER:
1030 	case CTF_K_FLOAT:
1031 	case CTF_K_POINTER:
1032 		/*
1033 		 * For pointers we could be a little stricter and require
1034 		 * both pointers to reference types which look vaguely
1035 		 * similar (for example, we could insist that the two types
1036 		 * have the same name). However, all we really care about
1037 		 * here is that the structure of the two types are the same,
1038 		 * and, in that regard, one pointer is as good as another.
1039 		 */
1040 		return (1);
1041 
1042 	case CTF_K_UNION:
1043 	case CTF_K_STRUCT:
1044 		/*
1045 		 * The test for the number of members is only strictly
1046 		 * necessary for unions since we'll find other problems with
1047 		 * structs. However, the extra check will do no harm.
1048 		 */
1049 		return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) &&
1050 		    mdb_ctf_member_iter(a, type_equals_cb, &b) == 0);
1051 
1052 	case CTF_K_ARRAY:
1053 		return (mdb_ctf_array_info(a, &aar) == 0 &&
1054 		    mdb_ctf_array_info(b, &bar) == 0 &&
1055 		    aar.mta_nelems == bar.mta_nelems &&
1056 		    type_equals(aar.mta_index, bar.mta_index) &&
1057 		    type_equals(aar.mta_contents, bar.mta_contents));
1058 	}
1059 
1060 	return (0);
1061 }
1062 
1063 
1064 typedef struct member {
1065 	char		*m_modbuf;
1066 	char		*m_tgtbuf;
1067 	const char	*m_tgtname;
1068 	mdb_ctf_id_t	m_tgtid;
1069 	uint_t		m_flags;
1070 } member_t;
1071 
1072 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *,
1073     const char *, uint_t);
1074 
1075 static int
1076 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
1077 {
1078 	member_t *mp = data;
1079 	char *modbuf = mp->m_modbuf;
1080 	mdb_ctf_id_t tgtmid;
1081 	char *tgtbuf = mp->m_tgtbuf;
1082 	ulong_t tgtoff;
1083 	char tgtname[128];
1084 
1085 	(void) mdb_snprintf(tgtname, sizeof (tgtname),
1086 	    "member %s of type %s", name, mp->m_tgtname);
1087 
1088 	if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
1089 		mdb_ctf_warn(mp->m_flags,
1090 		    "could not find %s\n", tgtname);
1091 		return (set_errno(EMDB_CTFNOMEMB));
1092 	}
1093 
1094 	return (vread_helper(modmid, modbuf + modoff / NBBY,
1095 	    tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags));
1096 }
1097 
1098 typedef struct enum_value {
1099 	int		*ev_modbuf;
1100 	const char	*ev_name;
1101 } enum_value_t;
1102 
1103 static int
1104 enum_cb(const char *name, int value, void *data)
1105 {
1106 	enum_value_t *ev = data;
1107 
1108 	if (strcmp(name, ev->ev_name) == 0) {
1109 		*ev->ev_modbuf = value;
1110 		return (1);
1111 	}
1112 	return (0);
1113 }
1114 
1115 static int
1116 vread_helper(mdb_ctf_id_t modid, char *modbuf,
1117     mdb_ctf_id_t tgtid, char *tgtbuf, const char *tgtname, uint_t flags)
1118 {
1119 	size_t modsz, tgtsz;
1120 	int modkind, tgtkind;
1121 	member_t mbr;
1122 	enum_value_t ev;
1123 	int ret;
1124 	mdb_ctf_arinfo_t tar, mar;
1125 	int i;
1126 	char typename[128];
1127 	char mdbtypename[128];
1128 	ctf_encoding_t tgt_encoding, mod_encoding;
1129 	boolean_t signed_int = B_FALSE;
1130 
1131 	if (mdb_ctf_type_name(tgtid, typename, sizeof (typename)) == NULL) {
1132 		(void) mdb_snprintf(typename, sizeof (typename),
1133 		    "#%ul", mdb_ctf_type_id(tgtid));
1134 	}
1135 	if (mdb_ctf_type_name(modid,
1136 	    mdbtypename, sizeof (mdbtypename)) == NULL) {
1137 		(void) mdb_snprintf(mdbtypename, sizeof (mdbtypename),
1138 		    "#%ul", mdb_ctf_type_id(modid));
1139 	}
1140 
1141 	if (tgtname == NULL)
1142 		tgtname = "";
1143 
1144 	/*
1145 	 * Resolve the types to their canonical form.
1146 	 */
1147 	(void) mdb_ctf_type_resolve(modid, &modid);
1148 	(void) mdb_ctf_type_resolve(tgtid, &tgtid);
1149 
1150 	if ((modkind = mdb_ctf_type_kind(modid)) == -1) {
1151 		mdb_ctf_warn(flags,
1152 		    "couldn't determine type kind of mdb module type %s\n",
1153 		    mdbtypename);
1154 		return (-1); /* errno is set for us */
1155 	}
1156 	if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) {
1157 		mdb_ctf_warn(flags,
1158 		    "couldn't determine type kind of %s\n", typename);
1159 		return (-1); /* errno is set for us */
1160 	}
1161 
1162 	if ((modsz = mdb_ctf_type_size(modid)) == -1UL) {
1163 		mdb_ctf_warn(flags, "couldn't determine type size of "
1164 		    "mdb module type %s\n", mdbtypename);
1165 		return (-1); /* errno is set for us */
1166 	}
1167 	if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) {
1168 		mdb_ctf_warn(flags, "couldn't determine size of %s (%s)\n",
1169 		    typename, tgtname);
1170 		return (-1); /* errno is set for us */
1171 	}
1172 
1173 	if (tgtkind == CTF_K_POINTER && modkind == CTF_K_INTEGER &&
1174 	    strcmp(mdbtypename, "uintptr_t") == 0) {
1175 		/* allow them to convert a pointer to a uintptr_t */
1176 		ASSERT(modsz == tgtsz);
1177 	} else if (tgtkind != modkind) {
1178 		mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n",
1179 		    typename, tgtname);
1180 		return (set_errno(EMDB_INCOMPAT));
1181 	}
1182 
1183 	switch (tgtkind) {
1184 	case CTF_K_INTEGER:
1185 	case CTF_K_FLOAT:
1186 		/*
1187 		 * Must determine if the target and module types have the same
1188 		 * encoding before we can copy them.
1189 		 */
1190 		if (mdb_ctf_type_encoding(tgtid, &tgt_encoding) != 0) {
1191 			mdb_ctf_warn(flags,
1192 			    "couldn't determine encoding of type %s (%s)\n",
1193 			    typename, tgtname);
1194 			return (-1); /* errno is set for us */
1195 		}
1196 		if (mdb_ctf_type_encoding(modid, &mod_encoding) != 0) {
1197 			mdb_ctf_warn(flags, "couldn't determine encoding of "
1198 			    "mdb module type %s\n", mdbtypename);
1199 			return (-1); /* errno is set for us */
1200 		}
1201 
1202 		if (modkind == CTF_K_INTEGER) {
1203 			if ((tgt_encoding.cte_format & CTF_INT_SIGNED) !=
1204 			    (mod_encoding.cte_format & CTF_INT_SIGNED)) {
1205 				mdb_ctf_warn(flags,
1206 				    "signedness mismatch between type "
1207 				    "%s (%s) and mdb module type %s\n",
1208 				    typename, tgtname, mdbtypename);
1209 				return (set_errno(EMDB_INCOMPAT));
1210 			}
1211 			signed_int =
1212 			    ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 0);
1213 		} else if (tgt_encoding.cte_format != mod_encoding.cte_format) {
1214 			mdb_ctf_warn(flags,
1215 			    "encoding mismatch (%#x != %#x) between type "
1216 			    "%s (%s) and mdb module type %s\n",
1217 			    tgt_encoding.cte_format, mod_encoding.cte_format,
1218 			    typename, tgtname, mdbtypename);
1219 			return (set_errno(EMDB_INCOMPAT));
1220 		}
1221 		/* FALLTHROUGH */
1222 	case CTF_K_POINTER:
1223 		/*
1224 		 * If the sizes don't match we need to be tricky to make
1225 		 * sure that the caller gets the correct data.
1226 		 */
1227 		if (modsz < tgtsz) {
1228 			mdb_ctf_warn(flags, "size of type %s (%s) is too "
1229 			    "large for mdb module type %s\n",
1230 			    typename, tgtname, mdbtypename);
1231 			return (set_errno(EMDB_INCOMPAT));
1232 		} else if (modsz > tgtsz) {
1233 			/* BEGIN CSTYLED */
1234 			/*
1235 			 * Fill modbuf with 1's for sign extension if target
1236 			 * buf is a signed integer and its value is negative.
1237 			 *
1238 			 *   S = sign bit (in most-significant byte)
1239 			 *
1240 			 *      BIG ENDIAN DATA
1241 			 *    +--------+--------+--------+--------+
1242 			 *    |S       |        |        |        |
1243 			 *    +--------+--------+--------+--------+
1244 			 *     0        1  ...            sz-1     sz
1245 			 *
1246 			 *      LITTLE ENDIAN DATA
1247 			 *    +--------+--------+--------+--------+
1248 			 *    |        |        |        |S       |
1249 			 *    +--------+--------+--------+--------+
1250 			 *     0        1  ...            sz-1     sz
1251 			 */
1252 			/* END CSTYLED */
1253 #ifdef _BIG_ENDIAN
1254 			if (signed_int && (tgtbuf[0] & 0x80) != 0)
1255 #else
1256 			if (signed_int && (tgtbuf[tgtsz - 1] & 0x80) != 0)
1257 #endif
1258 				(void) memset(modbuf, 0xFF, modsz);
1259 			else
1260 				bzero(modbuf, modsz);
1261 #ifdef _BIG_ENDIAN
1262 			bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz);
1263 #else
1264 			bcopy(tgtbuf, modbuf, tgtsz);
1265 #endif
1266 		} else {
1267 			bcopy(tgtbuf, modbuf, modsz);
1268 		}
1269 
1270 		return (0);
1271 
1272 	case CTF_K_ENUM:
1273 		if (modsz != tgtsz || modsz != sizeof (int)) {
1274 			mdb_ctf_warn(flags, "unexpected size of type %s (%s)\n",
1275 			    typename, tgtname);
1276 			return (set_errno(EMDB_INCOMPAT));
1277 		}
1278 
1279 		/*
1280 		 * Default to the same value as in the target.
1281 		 */
1282 		bcopy(tgtbuf, modbuf, sizeof (int));
1283 
1284 		/* LINTED */
1285 		i = *(int *)tgtbuf;
1286 
1287 		/* LINTED */
1288 		ev.ev_modbuf = (int *)modbuf;
1289 		ev.ev_name = mdb_ctf_enum_name(tgtid, i);
1290 		if (ev.ev_name == NULL) {
1291 			mdb_ctf_warn(flags,
1292 			    "unexpected value %u of enum type %s (%s)\n",
1293 			    i, typename, tgtname);
1294 			return (set_errno(EMDB_INCOMPAT));
1295 		}
1296 
1297 		ret = mdb_ctf_enum_iter(modid, enum_cb, &ev);
1298 		if (ret == 0) {
1299 			/* value not found */
1300 			mdb_ctf_warn(flags,
1301 			    "unexpected value %s (%u) of enum type %s (%s)\n",
1302 			    ev.ev_name, i, typename, tgtname);
1303 			return (set_errno(EMDB_INCOMPAT));
1304 		} else if (ret == 1) {
1305 			/* value found */
1306 			return (0);
1307 		} else if (ret == -1) {
1308 			mdb_ctf_warn(flags, "could not iterate enum %s (%s)\n",
1309 			    typename, tgtname);
1310 		}
1311 		return (ret);
1312 
1313 	case CTF_K_STRUCT:
1314 		mbr.m_modbuf = modbuf;
1315 		mbr.m_tgtbuf = tgtbuf;
1316 		mbr.m_tgtid = tgtid;
1317 		mbr.m_flags = flags;
1318 		mbr.m_tgtname = typename;
1319 
1320 		return (mdb_ctf_member_iter(modid, member_cb, &mbr));
1321 
1322 	case CTF_K_UNION:
1323 
1324 		/*
1325 		 * Unions are a little tricky. The only time it's truly
1326 		 * safe to read in a union is if no part of the union or
1327 		 * any of its component types have changed.  The correct
1328 		 * use of this feature is to read the containing structure,
1329 		 * figure out which component of the union is valid, compute
1330 		 * the location of that in the target and then read in
1331 		 * that part of the structure.
1332 		 */
1333 
1334 		if (!type_equals(modid, tgtid)) {
1335 			mdb_ctf_warn(flags, "inexact match for union %s (%s)\n",
1336 			    typename, tgtname);
1337 			return (set_errno(EMDB_INCOMPAT));
1338 		}
1339 
1340 		ASSERT(modsz == tgtsz);
1341 
1342 		bcopy(tgtbuf, modbuf, modsz);
1343 
1344 		return (0);
1345 
1346 	case CTF_K_ARRAY:
1347 		if (mdb_ctf_array_info(tgtid, &tar) != 0) {
1348 			mdb_ctf_warn(flags,
1349 			    "couldn't get array info for %s (%s)\n",
1350 			    typename, tgtname);
1351 			return (-1); /* errno is set for us */
1352 		}
1353 		if (mdb_ctf_array_info(modid, &mar) != 0) {
1354 			mdb_ctf_warn(flags,
1355 			    "couldn't get array info for mdb module type %s\n",
1356 			    mdbtypename);
1357 			return (-1); /* errno is set for us */
1358 		}
1359 
1360 		if (tar.mta_nelems != mar.mta_nelems) {
1361 			mdb_ctf_warn(flags,
1362 			    "unexpected array size (%u) for type %s (%s)\n",
1363 			    tar.mta_nelems, typename, tgtname);
1364 			return (set_errno(EMDB_INCOMPAT));
1365 		}
1366 
1367 		if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) {
1368 			mdb_ctf_warn(flags, "couldn't determine type size of "
1369 			    "mdb module type %s\n", mdbtypename);
1370 			return (-1); /* errno is set for us */
1371 		}
1372 		if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) {
1373 			mdb_ctf_warn(flags,
1374 			    "couldn't determine size of %s (%s)\n",
1375 			    typename, tgtname);
1376 			return (-1); /* errno is set for us */
1377 		}
1378 
1379 		for (i = 0; i < tar.mta_nelems; i++) {
1380 			ret = vread_helper(mar.mta_contents, modbuf + i * modsz,
1381 			    tar.mta_contents, tgtbuf + i * tgtsz,
1382 			    tgtname, flags);
1383 
1384 			if (ret != 0)
1385 				return (ret);
1386 		}
1387 
1388 		return (0);
1389 	}
1390 
1391 	mdb_ctf_warn(flags, "unsupported kind %d for type %s (%s)\n",
1392 	    modkind, typename, tgtname);
1393 	return (set_errno(EMDB_INCOMPAT));
1394 }
1395 
1396 /*
1397  * Like mdb_vread(), mdb_ctf_vread() is used to read from the target's
1398  * virtual address space.  However, mdb_ctf_vread() can be used to safely
1399  * read a complex type (e.g. a struct) from the target, even if MDB was compiled
1400  * against a different definition of that type (e.g. when debugging a crash
1401  * dump from an older release).
1402  *
1403  * Callers can achieve this by defining their own type which corresponds to the
1404  * type in the target, but contains only the members that the caller requires.
1405  * Using the CTF type information embedded in the target, mdb_ctf_vread will
1406  * find the required members in the target and fill in the caller's structure.
1407  * The members are located by name, and their types are verified to be
1408  * compatible.
1409  *
1410  * By convention, the caller will declare a type with the name "mdb_<type>",
1411  * where <type> is the name of the type in the target (e.g. mdb_zio_t).  This
1412  * type will contain the members that the caller is interested in.  For example:
1413  *
1414  * typedef struct mdb_zio {
1415  *         enum zio_type io_type;
1416  *         void *io_waiter;
1417  *         struct {
1418  *                 struct {
1419  *                         void *list_next;
1420  *                 } list_head;
1421  *         } io_parent_list;
1422  *         int io_error;
1423  * } mdb_zio_t;
1424  *
1425  * mdb_zio_t zio;
1426  * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0);
1427  *
1428  * If a given MDB module has different dcmds or walkers that need to read
1429  * different members from the same struct, then different "mdb_" types
1430  * should be declared for each caller.  By convention, these types should
1431  * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t
1432  * for ::findstack.  If the MDB module is compiled from several source files,
1433  * one must be especially careful to not define different types with the
1434  * same name in different source files, because the compiler can not detect
1435  * this error.
1436  *
1437  * Enums will also be translated by name, so the mdb module will receive
1438  * the enum value it expects even if the target has renumbered the enum.
1439  * Warning: it will therefore only work with enums are only used to store
1440  * legitimate enum values (not several values or-ed together).
1441  *
1442  * By default, if mdb_ctf_vread() can not find any members or enum values,
1443  * it will print a descriptive message (with mdb_warn()) and fail.
1444  * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message.
1445  * Additional flags can be used to ignore specific types of translation
1446  * failure, but should be used with caution, because they will silently leave
1447  * the caller's buffer uninitialized.
1448  */
1449 int
1450 mdb_ctf_vread(void *modbuf, const char *target_typename,
1451     const char *mdb_typename, uintptr_t addr, uint_t flags)
1452 {
1453 	ctf_file_t *mfp;
1454 	ctf_id_t mid;
1455 	void *tgtbuf;
1456 	size_t size;
1457 	mdb_ctf_id_t tgtid;
1458 	mdb_ctf_id_t modid;
1459 	mdb_module_t *mod;
1460 
1461 	if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
1462 		mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
1463 		    mod->mod_name);
1464 		return (set_errno(EMDB_NOCTF));
1465 	}
1466 
1467 	if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) {
1468 		mdb_ctf_warn(flags, "couldn't find ctf data for "
1469 		    "type %s in mdb module %s\n",
1470 		    mdb_typename, mod->mod_name);
1471 		return (set_errno(ctf_to_errno(ctf_errno(mfp))));
1472 	}
1473 
1474 	set_ctf_id(&modid, mfp, mid);
1475 
1476 	if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) {
1477 		mdb_ctf_warn(flags,
1478 		    "couldn't find type %s in target's ctf data\n",
1479 		    target_typename);
1480 		return (set_errno(EMDB_NOCTF));
1481 	}
1482 
1483 	/*
1484 	 * Read the data out of the target's address space.
1485 	 */
1486 	if ((size = mdb_ctf_type_size(tgtid)) == -1UL) {
1487 		mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
1488 		    target_typename);
1489 		return (-1); /* errno is set for us */
1490 	}
1491 
1492 	tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
1493 
1494 	if (mdb_vread(tgtbuf, size, addr) < 0) {
1495 		mdb_ctf_warn(flags, "couldn't read %s from %p\n",
1496 		    target_typename, addr);
1497 		return (-1); /* errno is set for us */
1498 	}
1499 
1500 	return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags));
1501 }
1502 
1503 /*
1504  * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
1505  * of the target's type vs the mdb module's type.  Use with complicated
1506  * types (e.g. structs) may result in unnecessary failure if a member of
1507  * the struct has been changed in the target, but is not actually needed
1508  * by the mdb module.  Use mdb_lookup_by_name() + mdb_ctf_vread() to
1509  * avoid this problem.
1510  */
1511 int
1512 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
1513 {
1514 	GElf_Sym sym;
1515 
1516 	if (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, name, &sym) != 0) {
1517 		mdb_ctf_warn(flags, "couldn't find symbol %s\n", name);
1518 		return (-1); /* errno is set for us */
1519 	}
1520 
1521 	return (mdb_ctf_vread(buf, typename, typename, sym.st_value, flags));
1522 }
1523 
1524 ctf_file_t *
1525 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va,
1526     Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp)
1527 {
1528 	ctf_sect_t ctdata, symtab, strtab;
1529 
1530 	ctdata.cts_name = ".SUNW_ctf";
1531 	ctdata.cts_type = SHT_PROGBITS;
1532 	ctdata.cts_flags = 0;
1533 	ctdata.cts_data = ctf_va;
1534 	ctdata.cts_size = ctf_size;
1535 	ctdata.cts_entsize = 1;
1536 	ctdata.cts_offset = 0;
1537 
1538 	symtab.cts_name = ".symtab";
1539 	symtab.cts_type = symhdr->sh_type;
1540 	symtab.cts_flags = symhdr->sh_flags;
1541 	symtab.cts_data = sym_va;
1542 	symtab.cts_size = symhdr->sh_size;
1543 	symtab.cts_entsize = symhdr->sh_entsize;
1544 	symtab.cts_offset = symhdr->sh_offset;
1545 
1546 	strtab.cts_name = ".strtab";
1547 	strtab.cts_type = strhdr->sh_type;
1548 	strtab.cts_flags = strhdr->sh_flags;
1549 	strtab.cts_data = str_va;
1550 	strtab.cts_size = strhdr->sh_size;
1551 	strtab.cts_entsize = strhdr->sh_entsize;
1552 	strtab.cts_offset = strhdr->sh_offset;
1553 
1554 	return (ctf_bufopen(&ctdata, &symtab, &strtab, errp));
1555 }
1556