xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_ctf.c (revision 28e4da25922bdfc5cba7ab29f47de911bbd78009)
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 (tgtkind != modkind) {
1163 		mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n",
1164 		    typename, tgtname);
1165 		return (set_errno(EMDB_INCOMPAT));
1166 	}
1167 
1168 	if ((modsz = mdb_ctf_type_size(modid)) == -1UL) {
1169 		mdb_ctf_warn(flags, "couldn't determine type size of "
1170 		    "mdb module type %s\n", mdbtypename);
1171 		return (-1); /* errno is set for us */
1172 	}
1173 	if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) {
1174 		mdb_ctf_warn(flags, "couldn't determine size of %s (%s)\n",
1175 		    typename, tgtname);
1176 		return (-1); /* errno is set for us */
1177 	}
1178 
1179 	switch (modkind) {
1180 	case CTF_K_INTEGER:
1181 	case CTF_K_FLOAT:
1182 		/*
1183 		 * Must determine if the target and module types have the same
1184 		 * encoding before we can copy them.
1185 		 */
1186 		if (mdb_ctf_type_encoding(tgtid, &tgt_encoding) != 0) {
1187 			mdb_ctf_warn(flags,
1188 			    "couldn't determine encoding of type %s (%s)\n",
1189 			    typename, tgtname);
1190 			return (-1); /* errno is set for us */
1191 		}
1192 		if (mdb_ctf_type_encoding(modid, &mod_encoding) != 0) {
1193 			mdb_ctf_warn(flags, "couldn't determine encoding of "
1194 			    "mdb module type %s\n", mdbtypename);
1195 			return (-1); /* errno is set for us */
1196 		}
1197 
1198 		if (modkind == CTF_K_INTEGER) {
1199 			if ((tgt_encoding.cte_format & CTF_INT_SIGNED) !=
1200 			    (mod_encoding.cte_format & CTF_INT_SIGNED)) {
1201 				mdb_ctf_warn(flags,
1202 				    "signedness mismatch between type "
1203 				    "%s (%s) and mdb module type %s\n",
1204 				    typename, tgtname, mdbtypename);
1205 				return (set_errno(EMDB_INCOMPAT));
1206 			}
1207 			signed_int =
1208 			    ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 0);
1209 		} else if (tgt_encoding.cte_format != mod_encoding.cte_format) {
1210 			mdb_ctf_warn(flags,
1211 			    "encoding mismatch (%#x != %#x) between type "
1212 			    "%s (%s) and mdb module type %s\n",
1213 			    tgt_encoding.cte_format, mod_encoding.cte_format,
1214 			    typename, tgtname, mdbtypename);
1215 			return (set_errno(EMDB_INCOMPAT));
1216 		}
1217 		/* FALLTHROUGH */
1218 	case CTF_K_POINTER:
1219 		/*
1220 		 * If the sizes don't match we need to be tricky to make
1221 		 * sure that the caller gets the correct data.
1222 		 */
1223 		if (modsz < tgtsz) {
1224 			mdb_ctf_warn(flags, "size of type %s (%s) is too "
1225 			    "large for mdb module type %s\n",
1226 			    typename, tgtname, mdbtypename);
1227 			return (set_errno(EMDB_INCOMPAT));
1228 		} else if (modsz > tgtsz) {
1229 			/* BEGIN CSTYLED */
1230 			/*
1231 			 * Fill modbuf with 1's for sign extension if target
1232 			 * buf is a signed integer and its value is negative.
1233 			 *
1234 			 *   S = sign bit (in most-significant byte)
1235 			 *
1236 			 *      BIG ENDIAN DATA
1237 			 *    +--------+--------+--------+--------+
1238 			 *    |S       |        |        |        |
1239 			 *    +--------+--------+--------+--------+
1240 			 *     0        1  ...            sz-1     sz
1241 			 *
1242 			 *      LITTLE ENDIAN DATA
1243 			 *    +--------+--------+--------+--------+
1244 			 *    |        |        |        |S       |
1245 			 *    +--------+--------+--------+--------+
1246 			 *     0        1  ...            sz-1     sz
1247 			 */
1248 			/* END CSTYLED */
1249 #ifdef _BIG_ENDIAN
1250 			if (signed_int && (tgtbuf[0] & 0x80) != 0)
1251 #else
1252 			if (signed_int && (tgtbuf[tgtsz - 1] & 0x80) != 0)
1253 #endif
1254 				(void) memset(modbuf, 0xFF, modsz);
1255 			else
1256 				bzero(modbuf, modsz);
1257 #ifdef _BIG_ENDIAN
1258 			bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz);
1259 #else
1260 			bcopy(tgtbuf, modbuf, tgtsz);
1261 #endif
1262 		} else {
1263 			bcopy(tgtbuf, modbuf, modsz);
1264 		}
1265 
1266 		return (0);
1267 
1268 	case CTF_K_ENUM:
1269 		if (modsz != tgtsz || modsz != sizeof (int)) {
1270 			mdb_ctf_warn(flags, "unexpected size of type %s (%s)\n",
1271 			    typename, tgtname);
1272 			return (set_errno(EMDB_INCOMPAT));
1273 		}
1274 
1275 		/*
1276 		 * Default to the same value as in the target.
1277 		 */
1278 		bcopy(tgtbuf, modbuf, sizeof (int));
1279 
1280 		/* LINTED */
1281 		i = *(int *)tgtbuf;
1282 
1283 		/* LINTED */
1284 		ev.ev_modbuf = (int *)modbuf;
1285 		ev.ev_name = mdb_ctf_enum_name(tgtid, i);
1286 		if (ev.ev_name == NULL) {
1287 			mdb_ctf_warn(flags,
1288 			    "unexpected value %u of enum type %s (%s)\n",
1289 			    i, typename, tgtname);
1290 			return (set_errno(EMDB_INCOMPAT));
1291 		}
1292 
1293 		ret = mdb_ctf_enum_iter(modid, enum_cb, &ev);
1294 		if (ret == 0) {
1295 			/* value not found */
1296 			mdb_ctf_warn(flags,
1297 			    "unexpected value %s (%u) of enum type %s (%s)\n",
1298 			    ev.ev_name, i, typename, tgtname);
1299 			return (set_errno(EMDB_INCOMPAT));
1300 		} else if (ret == 1) {
1301 			/* value found */
1302 			return (0);
1303 		} else if (ret == -1) {
1304 			mdb_ctf_warn(flags, "could not iterate enum %s (%s)\n",
1305 			    typename, tgtname);
1306 		}
1307 		return (ret);
1308 
1309 	case CTF_K_STRUCT:
1310 		mbr.m_modbuf = modbuf;
1311 		mbr.m_tgtbuf = tgtbuf;
1312 		mbr.m_tgtid = tgtid;
1313 		mbr.m_flags = flags;
1314 		mbr.m_tgtname = typename;
1315 
1316 		return (mdb_ctf_member_iter(modid, member_cb, &mbr));
1317 
1318 	case CTF_K_UNION:
1319 
1320 		/*
1321 		 * Unions are a little tricky. The only time it's truly
1322 		 * safe to read in a union is if no part of the union or
1323 		 * any of its component types have changed.  The correct
1324 		 * use of this feature is to read the containing structure,
1325 		 * figure out which component of the union is valid, compute
1326 		 * the location of that in the target and then read in
1327 		 * that part of the structure.
1328 		 */
1329 
1330 		if (!type_equals(modid, tgtid)) {
1331 			mdb_ctf_warn(flags, "inexact match for union %s (%s)\n",
1332 			    typename, tgtname);
1333 			return (set_errno(EMDB_INCOMPAT));
1334 		}
1335 
1336 		ASSERT(modsz == tgtsz);
1337 
1338 		bcopy(tgtbuf, modbuf, modsz);
1339 
1340 		return (0);
1341 
1342 	case CTF_K_ARRAY:
1343 		if (mdb_ctf_array_info(tgtid, &tar) != 0) {
1344 			mdb_ctf_warn(flags,
1345 			    "couldn't get array info for %s (%s)\n",
1346 			    typename, tgtname);
1347 			return (-1); /* errno is set for us */
1348 		}
1349 		if (mdb_ctf_array_info(modid, &mar) != 0) {
1350 			mdb_ctf_warn(flags,
1351 			    "couldn't get array info for mdb module type %s\n",
1352 			    mdbtypename);
1353 			return (-1); /* errno is set for us */
1354 		}
1355 
1356 		if (tar.mta_nelems != mar.mta_nelems) {
1357 			mdb_ctf_warn(flags,
1358 			    "unexpected array size (%u) for type %s (%s)\n",
1359 			    tar.mta_nelems, typename, tgtname);
1360 			return (set_errno(EMDB_INCOMPAT));
1361 		}
1362 
1363 		if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) {
1364 			mdb_ctf_warn(flags, "couldn't determine type size of "
1365 			    "mdb module type %s\n", mdbtypename);
1366 			return (-1); /* errno is set for us */
1367 		}
1368 		if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) {
1369 			mdb_ctf_warn(flags,
1370 			    "couldn't determine size of %s (%s)\n",
1371 			    typename, tgtname);
1372 			return (-1); /* errno is set for us */
1373 		}
1374 
1375 		for (i = 0; i < tar.mta_nelems; i++) {
1376 			ret = vread_helper(mar.mta_contents, modbuf + i * modsz,
1377 			    tar.mta_contents, tgtbuf + i * tgtsz,
1378 			    tgtname, flags);
1379 
1380 			if (ret != 0)
1381 				return (ret);
1382 		}
1383 
1384 		return (0);
1385 	}
1386 
1387 	mdb_ctf_warn(flags, "unsupported kind %d for type %s (%s)\n",
1388 	    modkind, typename, tgtname);
1389 	return (set_errno(EMDB_INCOMPAT));
1390 }
1391 
1392 /*
1393  * Like mdb_vread(), mdb_ctf_vread() is used to read from the target's
1394  * virtual address space.  However, mdb_ctf_vread() can be used to safely
1395  * read a complex type (e.g. a struct) from the target, even if MDB was compiled
1396  * against a different definition of that type (e.g. when debugging a crash
1397  * dump from an older release).
1398  *
1399  * Callers can achieve this by defining their own type which corresponds to the
1400  * type in the target, but contains only the members that the caller requires.
1401  * Using the CTF type information embedded in the target, mdb_ctf_vread will
1402  * find the required members in the target and fill in the caller's structure.
1403  * The members are located by name, and their types are verified to be
1404  * compatible.
1405  *
1406  * By convention, the caller will declare a type with the name "mdb_<type>",
1407  * where <type> is the name of the type in the target (e.g. mdb_zio_t).  This
1408  * type will contain the members that the caller is interested in.  For example:
1409  *
1410  * typedef struct mdb_zio {
1411  *         enum zio_type io_type;
1412  *         void *io_waiter;
1413  *         struct {
1414  *                 struct {
1415  *                         void *list_next;
1416  *                 } list_head;
1417  *         } io_parent_list;
1418  *         int io_error;
1419  * } mdb_zio_t;
1420  *
1421  * mdb_zio_t zio;
1422  * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0);
1423  *
1424  * If a given MDB module has different dcmds or walkers that need to read
1425  * different members from the same struct, then different "mdb_" types
1426  * should be declared for each caller.  By convention, these types should
1427  * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t
1428  * for ::findstack.  If the MDB module is compiled from several source files,
1429  * one must be especially careful to not define different types with the
1430  * same name in different source files, because the compiler can not detect
1431  * this error.
1432  *
1433  * Enums will also be translated by name, so the mdb module will receive
1434  * the enum value it expects even if the target has renumbered the enum.
1435  * Warning: it will therefore only work with enums are only used to store
1436  * legitimate enum values (not several values or-ed together).
1437  *
1438  * By default, if mdb_ctf_vread() can not find any members or enum values,
1439  * it will print a descriptive message (with mdb_warn()) and fail.
1440  * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message.
1441  * Additional flags can be used to ignore specific types of translation
1442  * failure, but should be used with caution, because they will silently leave
1443  * the caller's buffer uninitialized.
1444  */
1445 int
1446 mdb_ctf_vread(void *modbuf, const char *target_typename,
1447     const char *mdb_typename, uintptr_t addr, uint_t flags)
1448 {
1449 	ctf_file_t *mfp;
1450 	ctf_id_t mid;
1451 	void *tgtbuf;
1452 	size_t size;
1453 	mdb_ctf_id_t tgtid;
1454 	mdb_ctf_id_t modid;
1455 	mdb_module_t *mod;
1456 
1457 	if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
1458 		mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
1459 		    mod->mod_name);
1460 		return (set_errno(EMDB_NOCTF));
1461 	}
1462 
1463 	if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) {
1464 		mdb_ctf_warn(flags, "couldn't find ctf data for "
1465 		    "type %s in mdb module %s\n",
1466 		    mdb_typename, mod->mod_name);
1467 		return (set_errno(ctf_to_errno(ctf_errno(mfp))));
1468 	}
1469 
1470 	set_ctf_id(&modid, mfp, mid);
1471 
1472 	if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) {
1473 		mdb_ctf_warn(flags,
1474 		    "couldn't find type %s in target's ctf data\n",
1475 		    target_typename);
1476 		return (set_errno(EMDB_NOCTF));
1477 	}
1478 
1479 	/*
1480 	 * Read the data out of the target's address space.
1481 	 */
1482 	if ((size = mdb_ctf_type_size(tgtid)) == -1UL) {
1483 		mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
1484 		    target_typename);
1485 		return (-1); /* errno is set for us */
1486 	}
1487 
1488 	tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
1489 
1490 	if (mdb_vread(tgtbuf, size, addr) < 0) {
1491 		mdb_ctf_warn(flags, "couldn't read %s from %p\n",
1492 		    target_typename, addr);
1493 		return (-1); /* errno is set for us */
1494 	}
1495 
1496 	return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags));
1497 }
1498 
1499 /*
1500  * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
1501  * of the target's type vs the mdb module's type.  Use with complicated
1502  * types (e.g. structs) may result in unnecessary failure if a member of
1503  * the struct has been changed in the target, but is not actually needed
1504  * by the mdb module.  Use mdb_lookup_by_name() + mdb_ctf_vread() to
1505  * avoid this problem.
1506  */
1507 int
1508 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
1509 {
1510 	GElf_Sym sym;
1511 
1512 	if (mdb_lookup_by_name(name, &sym) != 0) {
1513 		mdb_ctf_warn(flags, "couldn't find symbol %s\n", name);
1514 		return (-1); /* errno is set for us */
1515 	}
1516 
1517 	return (mdb_ctf_vread(buf, typename, typename, sym.st_value, flags));
1518 }
1519 
1520 ctf_file_t *
1521 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va,
1522     Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp)
1523 {
1524 	ctf_sect_t ctdata, symtab, strtab;
1525 
1526 	ctdata.cts_name = ".SUNW_ctf";
1527 	ctdata.cts_type = SHT_PROGBITS;
1528 	ctdata.cts_flags = 0;
1529 	ctdata.cts_data = ctf_va;
1530 	ctdata.cts_size = ctf_size;
1531 	ctdata.cts_entsize = 1;
1532 	ctdata.cts_offset = 0;
1533 
1534 	symtab.cts_name = ".symtab";
1535 	symtab.cts_type = symhdr->sh_type;
1536 	symtab.cts_flags = symhdr->sh_flags;
1537 	symtab.cts_data = sym_va;
1538 	symtab.cts_size = symhdr->sh_size;
1539 	symtab.cts_entsize = symhdr->sh_entsize;
1540 	symtab.cts_offset = symhdr->sh_offset;
1541 
1542 	strtab.cts_name = ".strtab";
1543 	strtab.cts_type = strhdr->sh_type;
1544 	strtab.cts_flags = strhdr->sh_flags;
1545 	strtab.cts_data = str_va;
1546 	strtab.cts_size = strhdr->sh_size;
1547 	strtab.cts_entsize = strhdr->sh_entsize;
1548 	strtab.cts_offset = strhdr->sh_offset;
1549 
1550 	return (ctf_bufopen(&ctdata, &symtab, &strtab, errp));
1551 }
1552