xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_ctf.c (revision 53d6c69268ad98d311e74fb98d7514711585c1fa)
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, 2016 by Delphix. All rights reserved.
27  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
28  */
29 
30 #include <mdb/mdb_ctf.h>
31 #include <mdb/mdb_ctf_impl.h>
32 #include <mdb/mdb_err.h>
33 #include <mdb/mdb_modapi.h>
34 #include <mdb/mdb_string.h>
35 #include <mdb/mdb.h>
36 #include <mdb/mdb_debug.h>
37 
38 #include <libctf.h>
39 #include <string.h>
40 
41 typedef struct tnarg {
42 	mdb_tgt_t *tn_tgt;		/* target to use for lookup */
43 	const char *tn_name;		/* query string to lookup */
44 	ctf_file_t *tn_fp;		/* CTF container from match */
45 	ctf_id_t tn_id;			/* CTF type ID from match */
46 } tnarg_t;
47 
48 typedef struct type_iter {
49 	mdb_ctf_type_f *ti_cb;
50 	void *ti_arg;
51 	ctf_file_t *ti_fp;
52 } type_iter_t;
53 
54 typedef struct member_iter {
55 	mdb_ctf_member_f *mi_cb;
56 	void *mi_arg;
57 	ctf_file_t *mi_fp;
58 } member_iter_t;
59 
60 typedef struct type_visit {
61 	mdb_ctf_visit_f	*tv_cb;
62 	void		*tv_arg;
63 	ctf_file_t	*tv_fp;
64 	ulong_t		tv_base_offset;	/* used when recursing from type_cb() */
65 	int		tv_base_depth;	/* used when recursing from type_cb() */
66 	int		tv_min_depth;
67 } type_visit_t;
68 
69 typedef struct mbr_info {
70 	const char *mbr_member;
71 	ulong_t *mbr_offp;
72 	mdb_ctf_id_t *mbr_typep;
73 } mbr_info_t;
74 
75 typedef struct synth_intrinsic {
76 	const char *syn_name;
77 	ctf_encoding_t syn_enc;
78 	uint_t syn_kind;
79 } synth_intrinsic_t;
80 
81 typedef struct synth_typedef {
82 	const char *syt_src;
83 	const char *syt_targ;
84 } synth_typedef_t;
85 
86 /*
87  * As part of our support for synthetic types via ::typedef, we define a core
88  * set of types.
89  */
90 static const synth_intrinsic_t synth_builtins32[] = {
91 { "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER },
92 { "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
93 { "unsigned", { 0, 0, 32 }, CTF_K_INTEGER },
94 { "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
95 { "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
96 { "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
97 { "long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
98 { "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
99 { "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
100 { "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
101 { "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
102 { "signed long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
103 { "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
104 { "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
105 { "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER },
106 { "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER },
107 { "unsigned long", { 0, 0, 32 }, CTF_K_INTEGER },
108 { "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER },
109 { "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER },
110 { "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT },
111 { "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT },
112 { "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT },
113 { "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT },
114 { "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT },
115 { "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT },
116 { "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT },
117 { "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT },
118 { "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT },
119 { NULL, { 0, 0, 0}, 0 }
120 };
121 
122 static const synth_intrinsic_t synth_builtins64[] = {
123 { "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER },
124 { "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
125 { "unsigned", { 0, 0, 32 }, CTF_K_INTEGER },
126 { "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
127 { "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
128 { "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
129 { "long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
130 { "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
131 { "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
132 { "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
133 { "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
134 { "signed long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
135 { "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
136 { "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
137 { "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER },
138 { "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER },
139 { "unsigned long", { 0, 0, 64 }, CTF_K_INTEGER },
140 { "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER },
141 { "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER },
142 { "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT },
143 { "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT },
144 { "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT },
145 { "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT },
146 { "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT },
147 { "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT },
148 { "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT },
149 { "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT },
150 { "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT },
151 { NULL, { 0, 0, 0 }, 0 }
152 };
153 
154 static const synth_typedef_t synth_typedefs32[] = {
155 { "char", "int8_t" },
156 { "short", "int16_t" },
157 { "int", "int32_t" },
158 { "long long", "int64_t" },
159 { "int", "intptr_t" },
160 { "unsigned char", "uint8_t" },
161 { "unsigned short", "uint16_t" },
162 { "unsigned", "uint32_t" },
163 { "unsigned long long", "uint64_t" },
164 { "unsigned char", "uchar_t" },
165 { "unsigned short", "ushort_t" },
166 { "unsigned", "uint_t" },
167 { "unsigned long", "ulong_t" },
168 { "unsigned long long", "u_longlong_t" },
169 { "int", "ptrdiff_t" },
170 { "unsigned", "uintptr_t" },
171 { NULL, NULL }
172 };
173 
174 static const synth_typedef_t synth_typedefs64[] = {
175 { "char", "int8_t" },
176 { "short", "int16_t" },
177 { "int", "int32_t" },
178 { "long", "int64_t" },
179 { "long", "intptr_t" },
180 { "unsigned char", "uint8_t" },
181 { "unsigned short", "uint16_t" },
182 { "unsigned", "uint32_t" },
183 { "unsigned long", "uint64_t" },
184 { "unsigned char", "uchar_t" },
185 { "unsigned short", "ushort_t" },
186 { "unsigned", "uint_t" },
187 { "unsigned long", "ulong_t" },
188 { "unsigned long long", "u_longlong_t" },
189 { "long", "ptrdiff_t" },
190 { "unsigned long", "uintptr_t" },
191 { NULL, NULL }
192 };
193 
194 static void
195 set_ctf_id(mdb_ctf_id_t *p, ctf_file_t *fp, ctf_id_t id)
196 {
197 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
198 
199 	mcip->mci_fp = fp;
200 	mcip->mci_id = id;
201 }
202 
203 /*
204  * Callback function for mdb_tgt_object_iter used from name_to_type, below,
205  * to search the CTF namespace of each object file for a particular name.
206  */
207 /*ARGSUSED*/
208 static int
209 obj_lookup(void *data, const mdb_map_t *mp, const char *name)
210 {
211 	tnarg_t *tnp = data;
212 	ctf_file_t *fp;
213 	ctf_id_t id;
214 
215 	if ((fp = mdb_tgt_name_to_ctf(tnp->tn_tgt, name)) != NULL &&
216 	    (id = ctf_lookup_by_name(fp, tnp->tn_name)) != CTF_ERR) {
217 		tnp->tn_fp = fp;
218 		tnp->tn_id = id;
219 
220 		/*
221 		 * We may have found a forward declaration.  If we did, we'll
222 		 * note the ID and file pointer, but we'll keep searching in
223 		 * an attempt to find the real thing.  If we found something
224 		 * real (i.e. not a forward), we stop the iteration.
225 		 */
226 		return (ctf_type_kind(fp, id) == CTF_K_FORWARD ? 0 : -1);
227 	}
228 
229 	return (0);
230 }
231 
232 /*
233  * Convert a string type name with an optional leading object specifier into
234  * the corresponding CTF file container and type ID.  If an error occurs, we
235  * print an appropriate message and return NULL.
236  */
237 static ctf_file_t *
238 name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp)
239 {
240 	const char *object = MDB_TGT_OBJ_EXEC;
241 	ctf_file_t *fp = NULL;
242 	ctf_id_t id;
243 	tnarg_t arg;
244 	char *p, *s;
245 	char buf[MDB_SYM_NAMLEN];
246 	char *name = &buf[0];
247 
248 	(void) mdb_snprintf(buf, sizeof (buf), "%s", cname);
249 
250 	if ((p = strrsplit(name, '`')) != NULL) {
251 		/*
252 		 * We need to shuffle things around a little to support
253 		 * type names of the form "struct module`name".
254 		 */
255 		if ((s = strsplit(name, ' ')) != NULL) {
256 			bcopy(cname + (s - name), name, (p - s) - 1);
257 			name[(p - s) - 1] = '\0';
258 			bcopy(cname, name + (p - s), s - name);
259 			p = name + (p - s);
260 		}
261 		if (*name != '\0')
262 			object = name;
263 		name = p;
264 	}
265 
266 	/*
267 	 * Attempt to look up the name in the primary object file.  If this
268 	 * fails and the name was unscoped, search all remaining object files.
269 	 * Finally, search the synthetic types.
270 	 */
271 	if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL ||
272 	    (id = ctf_lookup_by_name(fp, name)) == CTF_ERR ||
273 	    ctf_type_kind(fp, id) == CTF_K_FORWARD) &&
274 	    object == MDB_TGT_OBJ_EXEC) {
275 
276 		arg.tn_tgt = t;
277 		arg.tn_name = name;
278 		arg.tn_fp = NULL;
279 		arg.tn_id = CTF_ERR;
280 
281 		(void) mdb_tgt_object_iter(t, obj_lookup, &arg);
282 
283 		if (arg.tn_id != CTF_ERR) {
284 			fp = arg.tn_fp;
285 			id = arg.tn_id;
286 		} else if (mdb.m_synth != NULL) {
287 			if ((id = ctf_lookup_by_name(mdb.m_synth,
288 			    name)) != CTF_ERR)
289 				fp = mdb.m_synth;
290 		}
291 	}
292 
293 	if (fp == NULL)
294 		return (NULL); /* errno is set for us */
295 
296 	if (id == CTF_ERR) {
297 		(void) set_errno(ctf_to_errno(ctf_errno(fp)));
298 		return (NULL);
299 	}
300 
301 	*idp = id;
302 	return (fp);
303 }
304 
305 /*
306  * Check to see if there is ctf data in the given object. This is useful
307  * so that we don't enter some loop where every call to lookup fails.
308  */
309 int
310 mdb_ctf_enabled_by_object(const char *object)
311 {
312 	mdb_tgt_t *t = mdb.m_target;
313 
314 	return (mdb_tgt_name_to_ctf(t, object) != NULL);
315 }
316 
317 int
318 mdb_ctf_lookup_by_name(const char *name, mdb_ctf_id_t *p)
319 {
320 	ctf_file_t *fp = NULL;
321 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
322 	mdb_tgt_t *t = mdb.m_target;
323 
324 	if (mcip == NULL)
325 		return (set_errno(EINVAL));
326 
327 	if ((fp = name_to_type(t, name, &mcip->mci_id)) == NULL) {
328 		mdb_ctf_type_invalidate(p);
329 		return (-1); /* errno is set for us */
330 	}
331 
332 	mcip->mci_fp = fp;
333 
334 	return (0);
335 }
336 
337 int
338 mdb_ctf_lookup_by_symbol(const GElf_Sym *symp, const mdb_syminfo_t *sip,
339     mdb_ctf_id_t *p)
340 {
341 	ctf_file_t *fp = NULL;
342 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
343 	mdb_tgt_t *t = mdb.m_target;
344 
345 	if (mcip == NULL)
346 		return (set_errno(EINVAL));
347 
348 	if (symp == NULL || sip == NULL) {
349 		mdb_ctf_type_invalidate(p);
350 		return (set_errno(EINVAL));
351 	}
352 
353 	if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL) {
354 		mdb_ctf_type_invalidate(p);
355 		return (-1); /* errno is set for us */
356 	}
357 
358 	if ((mcip->mci_id = ctf_lookup_by_symbol(fp, sip->sym_id)) == CTF_ERR) {
359 		mdb_ctf_type_invalidate(p);
360 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
361 	}
362 
363 	mcip->mci_fp = fp;
364 
365 	return (0);
366 }
367 
368 int
369 mdb_ctf_lookup_by_addr(uintptr_t addr, mdb_ctf_id_t *p)
370 {
371 	GElf_Sym sym;
372 	mdb_syminfo_t si;
373 	char name[MDB_SYM_NAMLEN];
374 	const mdb_map_t *mp;
375 	mdb_tgt_t *t = mdb.m_target;
376 	const char *obj, *c;
377 
378 	if (p == NULL)
379 		return (set_errno(EINVAL));
380 
381 	if (mdb_tgt_lookup_by_addr(t, addr, MDB_TGT_SYM_EXACT, name,
382 	    sizeof (name), NULL, NULL) == -1) {
383 		mdb_ctf_type_invalidate(p);
384 		return (-1); /* errno is set for us */
385 	}
386 
387 	if ((c = strrsplit(name, '`')) != NULL) {
388 		obj = name;
389 	} else {
390 		if ((mp = mdb_tgt_addr_to_map(t, addr)) == NULL) {
391 			mdb_ctf_type_invalidate(p);
392 			return (-1); /* errno is set for us */
393 		}
394 
395 		obj = mp->map_name;
396 		c = name;
397 	}
398 
399 	if (mdb_tgt_lookup_by_name(t, obj, c, &sym, &si) == -1) {
400 		mdb_ctf_type_invalidate(p);
401 		return (-1); /* errno is set for us */
402 	}
403 
404 	return (mdb_ctf_lookup_by_symbol(&sym, &si, p));
405 }
406 
407 int
408 mdb_ctf_module_lookup(const char *name, mdb_ctf_id_t *p)
409 {
410 	ctf_file_t *fp;
411 	ctf_id_t id;
412 	mdb_module_t *mod;
413 
414 	if ((mod = mdb_get_module()) == NULL)
415 		return (set_errno(EMDB_CTX));
416 
417 	if ((fp = mod->mod_ctfp) == NULL)
418 		return (set_errno(EMDB_NOCTF));
419 
420 	if ((id = ctf_lookup_by_name(fp, name)) == CTF_ERR)
421 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
422 
423 	set_ctf_id(p, fp, id);
424 
425 	return (0);
426 }
427 
428 /*ARGSUSED*/
429 int
430 mdb_ctf_func_info(const GElf_Sym *symp, const mdb_syminfo_t *sip,
431     mdb_ctf_funcinfo_t *mfp)
432 {
433 	ctf_file_t *fp = NULL;
434 	ctf_funcinfo_t f;
435 	mdb_tgt_t *t = mdb.m_target;
436 	char name[MDB_SYM_NAMLEN];
437 	const mdb_map_t *mp;
438 	mdb_syminfo_t si;
439 	int err;
440 
441 	if (symp == NULL || mfp == NULL)
442 		return (set_errno(EINVAL));
443 
444 	/*
445 	 * In case the input symbol came from a merged or private symbol table,
446 	 * re-lookup the address as a symbol, and then perform a fully scoped
447 	 * lookup of that symbol name to get the mdb_syminfo_t for its CTF.
448 	 */
449 	if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL ||
450 	    (mp = mdb_tgt_addr_to_map(t, symp->st_value)) == NULL ||
451 	    mdb_tgt_lookup_by_addr(t, symp->st_value, MDB_TGT_SYM_FUZZY,
452 	    name, sizeof (name), NULL, NULL) != 0)
453 		return (-1); /* errno is set for us */
454 
455 	if (strchr(name, '`') != NULL)
456 		err = mdb_tgt_lookup_by_scope(t, name, NULL, &si);
457 	else
458 		err = mdb_tgt_lookup_by_name(t, mp->map_name, name, NULL, &si);
459 
460 	if (err != 0)
461 		return (-1); /* errno is set for us */
462 
463 	if (ctf_func_info(fp, si.sym_id, &f) == CTF_ERR)
464 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
465 
466 	set_ctf_id(&mfp->mtf_return, fp, f.ctc_return);
467 	mfp->mtf_argc = f.ctc_argc;
468 	mfp->mtf_flags = f.ctc_flags;
469 	mfp->mtf_symidx = si.sym_id;
470 
471 	return (0);
472 }
473 
474 int
475 mdb_ctf_func_args(const mdb_ctf_funcinfo_t *funcp, uint_t len,
476     mdb_ctf_id_t *argv)
477 {
478 	ctf_file_t *fp;
479 	ctf_id_t cargv[32];
480 	int i;
481 
482 	if (len > (sizeof (cargv) / sizeof (cargv[0])))
483 		return (set_errno(EINVAL));
484 
485 	if (funcp == NULL || argv == NULL)
486 		return (set_errno(EINVAL));
487 
488 	fp = mdb_ctf_type_file(funcp->mtf_return);
489 
490 	if (ctf_func_args(fp, funcp->mtf_symidx, len, cargv) == CTF_ERR)
491 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
492 
493 	for (i = MIN(len, funcp->mtf_argc) - 1; i >= 0; i--) {
494 		set_ctf_id(&argv[i], fp, cargv[i]);
495 	}
496 
497 	return (0);
498 }
499 
500 void
501 mdb_ctf_type_invalidate(mdb_ctf_id_t *idp)
502 {
503 	set_ctf_id(idp, NULL, CTF_ERR);
504 }
505 
506 int
507 mdb_ctf_type_valid(mdb_ctf_id_t id)
508 {
509 	return (((mdb_ctf_impl_t *)&id)->mci_id != CTF_ERR);
510 }
511 
512 int
513 mdb_ctf_type_cmp(mdb_ctf_id_t aid, mdb_ctf_id_t bid)
514 {
515 	mdb_ctf_impl_t *aidp = (mdb_ctf_impl_t *)&aid;
516 	mdb_ctf_impl_t *bidp = (mdb_ctf_impl_t *)&bid;
517 
518 	return (ctf_type_cmp(aidp->mci_fp, aidp->mci_id,
519 	    bidp->mci_fp, bidp->mci_id));
520 }
521 
522 int
523 mdb_ctf_type_resolve(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
524 {
525 	ctf_id_t id;
526 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&mid;
527 
528 	if ((id = ctf_type_resolve(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
529 		if (outp)
530 			mdb_ctf_type_invalidate(outp);
531 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
532 	}
533 
534 	if (ctf_type_kind(idp->mci_fp, id) == CTF_K_FORWARD) {
535 		char name[MDB_SYM_NAMLEN];
536 		mdb_ctf_id_t lookup_id;
537 
538 		if (ctf_type_name(idp->mci_fp, id, name, sizeof (name)) !=
539 		    NULL &&
540 		    mdb_ctf_lookup_by_name(name, &lookup_id) == 0 &&
541 		    outp != NULL) {
542 			*outp = lookup_id;
543 			return (0);
544 		}
545 	}
546 
547 	if (outp != NULL)
548 		set_ctf_id(outp, idp->mci_fp, id);
549 
550 	return (0);
551 }
552 
553 char *
554 mdb_ctf_type_name(mdb_ctf_id_t id, char *buf, size_t len)
555 {
556 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
557 	char *ret;
558 
559 	if (!mdb_ctf_type_valid(id)) {
560 		(void) set_errno(EINVAL);
561 		return (NULL);
562 	}
563 
564 	ret = ctf_type_name(idp->mci_fp, idp->mci_id, buf, len);
565 	if (ret == NULL)
566 		(void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
567 
568 	return (ret);
569 }
570 
571 ssize_t
572 mdb_ctf_type_size(mdb_ctf_id_t id)
573 {
574 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
575 	ssize_t ret;
576 
577 	/* resolve the type in case there's a forward declaration */
578 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
579 		return (ret);
580 
581 	if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR)
582 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
583 
584 	return (ret);
585 }
586 
587 int
588 mdb_ctf_type_kind(mdb_ctf_id_t id)
589 {
590 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
591 	int ret;
592 
593 	if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR)
594 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
595 
596 	return (ret);
597 }
598 
599 int
600 mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
601 {
602 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&mid;
603 	ctf_id_t id;
604 
605 	if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
606 		if (outp)
607 			mdb_ctf_type_invalidate(outp);
608 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
609 	}
610 
611 	if (outp != NULL)
612 		set_ctf_id(outp, idp->mci_fp, id);
613 
614 	return (0);
615 }
616 
617 
618 int
619 mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep)
620 {
621 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
622 
623 	if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR)
624 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
625 
626 	return (0);
627 }
628 
629 /*
630  * callback proxy for mdb_ctf_type_visit
631  */
632 static int
633 type_cb(const char *name, ctf_id_t type, ulong_t off, int depth, void *arg)
634 {
635 	type_visit_t *tvp = arg;
636 	mdb_ctf_id_t id;
637 	mdb_ctf_id_t base;
638 	mdb_ctf_impl_t *basep = (mdb_ctf_impl_t *)&base;
639 
640 	int ret;
641 
642 	if (depth < tvp->tv_min_depth)
643 		return (0);
644 
645 	off += tvp->tv_base_offset;
646 	depth += tvp->tv_base_depth;
647 
648 	set_ctf_id(&id, tvp->tv_fp, type);
649 
650 	(void) mdb_ctf_type_resolve(id, &base);
651 	if ((ret = tvp->tv_cb(name, id, base, off, depth, tvp->tv_arg)) != 0)
652 		return (ret);
653 
654 	/*
655 	 * If the type resolves to a type in a different file, we must have
656 	 * followed a forward declaration.  We need to recurse into the
657 	 * new type.
658 	 */
659 	if (basep->mci_fp != tvp->tv_fp && mdb_ctf_type_valid(base)) {
660 		type_visit_t tv;
661 
662 		tv.tv_cb = tvp->tv_cb;
663 		tv.tv_arg = tvp->tv_arg;
664 		tv.tv_fp = basep->mci_fp;
665 
666 		tv.tv_base_offset = off;
667 		tv.tv_base_depth = depth;
668 		tv.tv_min_depth = 1;	/* depth = 0 has already been done */
669 
670 		ret = ctf_type_visit(basep->mci_fp, basep->mci_id,
671 		    type_cb, &tv);
672 	}
673 	return (ret);
674 }
675 
676 int
677 mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg)
678 {
679 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
680 	type_visit_t tv;
681 	int ret;
682 
683 	tv.tv_cb = func;
684 	tv.tv_arg = arg;
685 	tv.tv_fp = idp->mci_fp;
686 	tv.tv_base_offset = 0;
687 	tv.tv_base_depth = 0;
688 	tv.tv_min_depth = 0;
689 
690 	ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv);
691 
692 	if (ret == CTF_ERR)
693 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
694 
695 	return (ret);
696 }
697 
698 int
699 mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp)
700 {
701 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
702 	ctf_arinfo_t car;
703 
704 	if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR)
705 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
706 
707 	set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents);
708 	set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index);
709 
710 	arp->mta_nelems = car.ctr_nelems;
711 
712 	return (0);
713 }
714 
715 const char *
716 mdb_ctf_enum_name(mdb_ctf_id_t id, int value)
717 {
718 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
719 	const char *ret;
720 
721 	/* resolve the type in case there's a forward declaration */
722 	if (mdb_ctf_type_resolve(id, &id) != 0)
723 		return (NULL);
724 
725 	if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL)
726 		(void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
727 
728 	return (ret);
729 }
730 
731 /*
732  * callback proxy for mdb_ctf_member_iter
733  */
734 static int
735 member_iter_cb(const char *name, ctf_id_t type, ulong_t off, void *data)
736 {
737 	member_iter_t *mip = data;
738 	mdb_ctf_id_t id;
739 
740 	set_ctf_id(&id, mip->mi_fp, type);
741 
742 	return (mip->mi_cb(name, id, off, mip->mi_arg));
743 }
744 
745 int
746 mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data)
747 {
748 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
749 	member_iter_t mi;
750 	int ret;
751 
752 	/* resolve the type in case there's a forward declaration */
753 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
754 		return (ret);
755 
756 	mi.mi_cb = cb;
757 	mi.mi_arg = data;
758 	mi.mi_fp = idp->mci_fp;
759 
760 	ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi);
761 
762 	if (ret == CTF_ERR)
763 		return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
764 
765 	return (ret);
766 }
767 
768 int
769 mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data)
770 {
771 	mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
772 	int ret;
773 
774 	/* resolve the type in case there's a forward declaration */
775 	if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
776 		return (ret);
777 
778 	return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data));
779 }
780 
781 /*
782  * callback proxy for mdb_ctf_type_iter
783  */
784 static int
785 type_iter_cb(ctf_id_t type, void *data)
786 {
787 	type_iter_t *tip = data;
788 	mdb_ctf_id_t id;
789 
790 	set_ctf_id(&id, tip->ti_fp, type);
791 
792 	return (tip->ti_cb(id, tip->ti_arg));
793 }
794 
795 int
796 mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data)
797 {
798 	ctf_file_t *fp;
799 	mdb_tgt_t *t = mdb.m_target;
800 	int ret;
801 	type_iter_t ti;
802 
803 	if (object == MDB_CTF_SYNTHETIC_ITER)
804 		fp = mdb.m_synth;
805 	else
806 		fp = mdb_tgt_name_to_ctf(t, object);
807 
808 	if (fp == NULL)
809 		return (-1);
810 
811 	ti.ti_cb = cb;
812 	ti.ti_arg = data;
813 	ti.ti_fp = fp;
814 
815 	if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR)
816 		return (set_errno(ctf_to_errno(ctf_errno(fp))));
817 
818 	return (ret);
819 }
820 
821 /* utility functions */
822 
823 ctf_id_t
824 mdb_ctf_type_id(mdb_ctf_id_t id)
825 {
826 	return (((mdb_ctf_impl_t *)&id)->mci_id);
827 }
828 
829 ctf_file_t *
830 mdb_ctf_type_file(mdb_ctf_id_t id)
831 {
832 	return (((mdb_ctf_impl_t *)&id)->mci_fp);
833 }
834 
835 static int
836 member_info_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
837 {
838 	mbr_info_t *mbrp = data;
839 
840 	if (strcmp(name, mbrp->mbr_member) == 0) {
841 		if (mbrp->mbr_offp != NULL)
842 			*(mbrp->mbr_offp) = off;
843 		if (mbrp->mbr_typep != NULL)
844 			*(mbrp->mbr_typep) = id;
845 
846 		return (1);
847 	}
848 
849 	return (0);
850 }
851 
852 int
853 mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp,
854     mdb_ctf_id_t *typep)
855 {
856 	mbr_info_t mbr;
857 	int rc;
858 
859 	mbr.mbr_member = member;
860 	mbr.mbr_offp = offp;
861 	mbr.mbr_typep = typep;
862 
863 	rc = mdb_ctf_member_iter(id, member_info_cb, &mbr);
864 
865 	/* couldn't get member list */
866 	if (rc == -1)
867 		return (-1); /* errno is set for us */
868 
869 	/* not a member */
870 	if (rc == 0)
871 		return (set_errno(EMDB_CTFNOMEMB));
872 
873 	return (0);
874 }
875 
876 /*
877  * Returns offset in _bits_ in *retp.
878  */
879 int
880 mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp)
881 {
882 	return (mdb_ctf_member_info(id, member, retp, NULL));
883 }
884 
885 /*
886  * Returns offset in _bytes_, or -1 on failure.
887  */
888 int
889 mdb_ctf_offsetof_by_name(const char *type, const char *member)
890 {
891 	mdb_ctf_id_t id;
892 	ulong_t off;
893 
894 	if (mdb_ctf_lookup_by_name(type, &id) == -1) {
895 		mdb_warn("couldn't find type %s", type);
896 		return (-1);
897 	}
898 
899 	if (mdb_ctf_offsetof(id, member, &off) == -1) {
900 		mdb_warn("couldn't find member %s of type %s", member, type);
901 		return (-1);
902 	}
903 	if (off % 8 != 0) {
904 		mdb_warn("member %s of type %s is an unsupported bitfield\n",
905 		    member, type);
906 		return (-1);
907 	}
908 	off /= 8;
909 
910 	return (off);
911 }
912 
913 ssize_t
914 mdb_ctf_sizeof_by_name(const char *type)
915 {
916 	mdb_ctf_id_t id;
917 	ssize_t size;
918 
919 	if (mdb_ctf_lookup_by_name(type, &id) == -1) {
920 		mdb_warn("couldn't find type %s", type);
921 		return (-1);
922 	}
923 
924 	if ((size = mdb_ctf_type_size(id)) == -1) {
925 		mdb_warn("couldn't determine type size of %s", type);
926 		return (-1);
927 	}
928 
929 	return (size);
930 }
931 
932 /*ARGSUSED*/
933 static int
934 num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
935 {
936 	int *count = data;
937 	*count = *count + 1;
938 	return (0);
939 }
940 
941 int
942 mdb_ctf_num_members(mdb_ctf_id_t id)
943 {
944 	int count = 0;
945 
946 	if (mdb_ctf_member_iter(id, num_members_cb, &count) != 0)
947 		return (-1); /* errno is set for us */
948 
949 	return (count);
950 }
951 
952 typedef struct mbr_contains {
953 	char **mbc_bufp;
954 	size_t *mbc_lenp;
955 	ulong_t *mbc_offp;
956 	mdb_ctf_id_t *mbc_idp;
957 	ssize_t mbc_total;
958 } mbr_contains_t;
959 
960 static int
961 offset_to_name_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
962 {
963 	mbr_contains_t *mbc = data;
964 	ulong_t size;
965 	ctf_encoding_t e;
966 	size_t n;
967 
968 	if (*mbc->mbc_offp < off)
969 		return (0);
970 
971 	if (mdb_ctf_type_encoding(id, &e) == -1)
972 		size = mdb_ctf_type_size(id) * NBBY;
973 	else
974 		size = e.cte_bits;
975 
976 	if (off + size <= *mbc->mbc_offp)
977 		return (0);
978 
979 	n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "%s", name);
980 	mbc->mbc_total += n;
981 	if (n > *mbc->mbc_lenp)
982 		n = *mbc->mbc_lenp;
983 
984 	*mbc->mbc_lenp -= n;
985 	*mbc->mbc_bufp += n;
986 
987 	*mbc->mbc_offp -= off;
988 	*mbc->mbc_idp = id;
989 
990 	return (1);
991 }
992 
993 ssize_t
994 mdb_ctf_offset_to_name(mdb_ctf_id_t id, ulong_t off, char *buf, size_t len,
995     int dot, mdb_ctf_id_t *midp, ulong_t *moffp)
996 {
997 	size_t size;
998 	size_t n;
999 	mbr_contains_t mbc;
1000 
1001 	if (!mdb_ctf_type_valid(id))
1002 		return (set_errno(EINVAL));
1003 
1004 	/*
1005 	 * Quick sanity check to make sure the given offset is within
1006 	 * this scope of this type.
1007 	 */
1008 	if (mdb_ctf_type_size(id) * NBBY <= off)
1009 		return (set_errno(EINVAL));
1010 
1011 	mbc.mbc_bufp = &buf;
1012 	mbc.mbc_lenp = &len;
1013 	mbc.mbc_offp = &off;
1014 	mbc.mbc_idp = &id;
1015 	mbc.mbc_total = 0;
1016 
1017 	*buf = '\0';
1018 
1019 	for (;;) {
1020 		/*
1021 		 * Check for an exact match.
1022 		 */
1023 		if (off == 0)
1024 			break;
1025 
1026 		(void) mdb_ctf_type_resolve(id, &id);
1027 
1028 		/*
1029 		 * Find the member that contains this offset.
1030 		 */
1031 		switch (mdb_ctf_type_kind(id)) {
1032 		case CTF_K_ARRAY: {
1033 			mdb_ctf_arinfo_t ar;
1034 			uint_t index;
1035 
1036 			(void) mdb_ctf_array_info(id, &ar);
1037 			size = mdb_ctf_type_size(ar.mta_contents) * NBBY;
1038 			index = off / size;
1039 
1040 			id = ar.mta_contents;
1041 			off %= size;
1042 
1043 			n = mdb_snprintf(buf, len, "[%u]", index);
1044 			mbc.mbc_total += n;
1045 			if (n > len)
1046 				n = len;
1047 
1048 			buf += n;
1049 			len -= n;
1050 			break;
1051 		}
1052 
1053 		case CTF_K_STRUCT: {
1054 			int ret;
1055 
1056 			/*
1057 			 * Find the member that contains this offset
1058 			 * and continue.
1059 			 */
1060 
1061 			if (dot) {
1062 				mbc.mbc_total++;
1063 				if (len != 0) {
1064 					*buf++ = '.';
1065 					*buf = '\0';
1066 					len--;
1067 				}
1068 			}
1069 
1070 			ret = mdb_ctf_member_iter(id, offset_to_name_cb, &mbc);
1071 			if (ret == -1)
1072 				return (-1); /* errno is set for us */
1073 
1074 			/*
1075 			 * If we did not find a member containing this offset
1076 			 * (due to holes in the structure), return EINVAL.
1077 			 */
1078 			if (ret == 0)
1079 				return (set_errno(EINVAL));
1080 
1081 			break;
1082 		}
1083 
1084 		case CTF_K_UNION:
1085 			/*
1086 			 * Treat unions like atomic entities since we can't
1087 			 * do more than guess which member of the union
1088 			 * might be the intended one.
1089 			 */
1090 			goto done;
1091 
1092 		case CTF_K_INTEGER:
1093 		case CTF_K_FLOAT:
1094 		case CTF_K_POINTER:
1095 		case CTF_K_ENUM:
1096 			goto done;
1097 
1098 		default:
1099 			return (set_errno(EINVAL));
1100 		}
1101 
1102 		dot = 1;
1103 	}
1104 done:
1105 	if (midp != NULL)
1106 		*midp = id;
1107 	if (moffp != NULL)
1108 		*moffp = off;
1109 
1110 	return (mbc.mbc_total);
1111 }
1112 
1113 static void
1114 mdb_ctf_warn(uint_t flags, const char *format, ...)
1115 {
1116 	va_list alist;
1117 
1118 	if (flags & MDB_CTF_VREAD_QUIET)
1119 		return;
1120 
1121 	va_start(alist, format);
1122 	vwarn(format, alist);
1123 	va_end(alist);
1124 }
1125 
1126 /*
1127  * Check if two types are structurally the same rather than logically
1128  * the same. That is to say that two types are equal if they have the
1129  * same logical structure rather than having the same ids in CTF-land.
1130  */
1131 static int type_equals(mdb_ctf_id_t, mdb_ctf_id_t);
1132 
1133 static int
1134 type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data)
1135 {
1136 	mdb_ctf_id_t b = *(mdb_ctf_id_t *)data;
1137 	ulong_t boff;
1138 	mdb_ctf_id_t bmem;
1139 
1140 	/*
1141 	 * Look up the corresponding member in the other composite type.
1142 	 */
1143 	if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0)
1144 		return (1);
1145 
1146 	/*
1147 	 * We don't allow members to be shuffled around.
1148 	 */
1149 	if (aoff != boff)
1150 		return (1);
1151 
1152 	return (type_equals(amem, bmem) ? 0 : 1);
1153 }
1154 
1155 static int
1156 type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b)
1157 {
1158 	size_t asz, bsz;
1159 	int akind, bkind;
1160 	mdb_ctf_arinfo_t aar, bar;
1161 
1162 	/*
1163 	 * Resolve both types down to their fundamental types, and make
1164 	 * sure their sizes and kinds match.
1165 	 */
1166 	if (mdb_ctf_type_resolve(a, &a) != 0 ||
1167 	    mdb_ctf_type_resolve(b, &b) != 0 ||
1168 	    (asz = mdb_ctf_type_size(a)) == -1UL ||
1169 	    (bsz = mdb_ctf_type_size(b)) == -1UL ||
1170 	    (akind = mdb_ctf_type_kind(a)) == -1 ||
1171 	    (bkind = mdb_ctf_type_kind(b)) == -1 ||
1172 	    asz != bsz || akind != bkind) {
1173 		return (0);
1174 	}
1175 
1176 	switch (akind) {
1177 	case CTF_K_INTEGER:
1178 	case CTF_K_FLOAT:
1179 	case CTF_K_POINTER:
1180 		/*
1181 		 * For pointers we could be a little stricter and require
1182 		 * both pointers to reference types which look vaguely
1183 		 * similar (for example, we could insist that the two types
1184 		 * have the same name). However, all we really care about
1185 		 * here is that the structure of the two types are the same,
1186 		 * and, in that regard, one pointer is as good as another.
1187 		 */
1188 		return (1);
1189 
1190 	case CTF_K_UNION:
1191 	case CTF_K_STRUCT:
1192 		/*
1193 		 * The test for the number of members is only strictly
1194 		 * necessary for unions since we'll find other problems with
1195 		 * structs. However, the extra check will do no harm.
1196 		 */
1197 		return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) &&
1198 		    mdb_ctf_member_iter(a, type_equals_cb, &b) == 0);
1199 
1200 	case CTF_K_ARRAY:
1201 		return (mdb_ctf_array_info(a, &aar) == 0 &&
1202 		    mdb_ctf_array_info(b, &bar) == 0 &&
1203 		    aar.mta_nelems == bar.mta_nelems &&
1204 		    type_equals(aar.mta_index, bar.mta_index) &&
1205 		    type_equals(aar.mta_contents, bar.mta_contents));
1206 	}
1207 
1208 	return (0);
1209 }
1210 
1211 
1212 typedef struct member {
1213 	char		*m_modbuf;
1214 	char		*m_tgtbuf;
1215 	const char	*m_tgtname;
1216 	mdb_ctf_id_t	m_tgtid;
1217 	uint_t		m_flags;
1218 } member_t;
1219 
1220 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *,
1221     const char *, uint_t);
1222 
1223 static int
1224 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
1225 {
1226 	member_t *mp = data;
1227 	char *modbuf = mp->m_modbuf;
1228 	mdb_ctf_id_t tgtmid;
1229 	char *tgtbuf = mp->m_tgtbuf;
1230 	ulong_t tgtoff;
1231 	char tgtname[128];
1232 
1233 	(void) mdb_snprintf(tgtname, sizeof (tgtname),
1234 	    "member %s of type %s", name, mp->m_tgtname);
1235 
1236 	if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
1237 		mdb_ctf_warn(mp->m_flags,
1238 		    "could not find %s\n", tgtname);
1239 		return (set_errno(EMDB_CTFNOMEMB));
1240 	}
1241 
1242 	return (vread_helper(modmid, modbuf + modoff / NBBY,
1243 	    tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags));
1244 }
1245 
1246 typedef struct enum_value {
1247 	int		*ev_modbuf;
1248 	const char	*ev_name;
1249 } enum_value_t;
1250 
1251 static int
1252 enum_cb(const char *name, int value, void *data)
1253 {
1254 	enum_value_t *ev = data;
1255 
1256 	if (strcmp(name, ev->ev_name) == 0) {
1257 		*ev->ev_modbuf = value;
1258 		return (1);
1259 	}
1260 	return (0);
1261 }
1262 
1263 static int
1264 vread_helper(mdb_ctf_id_t modid, char *modbuf,
1265     mdb_ctf_id_t tgtid, char *tgtbuf, const char *tgtname, uint_t flags)
1266 {
1267 	size_t modsz, tgtsz;
1268 	int modkind, tgtkind, mod_members;
1269 	member_t mbr;
1270 	enum_value_t ev;
1271 	int ret;
1272 	mdb_ctf_arinfo_t tar, mar;
1273 	int i;
1274 	char typename[128];
1275 	char mdbtypename[128];
1276 	ctf_encoding_t tgt_encoding, mod_encoding;
1277 	boolean_t signed_int = B_FALSE;
1278 
1279 	if (mdb_ctf_type_name(tgtid, typename, sizeof (typename)) == NULL) {
1280 		(void) mdb_snprintf(typename, sizeof (typename),
1281 		    "#%ul", mdb_ctf_type_id(tgtid));
1282 	}
1283 	if (mdb_ctf_type_name(modid,
1284 	    mdbtypename, sizeof (mdbtypename)) == NULL) {
1285 		(void) mdb_snprintf(mdbtypename, sizeof (mdbtypename),
1286 		    "#%ul", mdb_ctf_type_id(modid));
1287 	}
1288 
1289 	if (tgtname == NULL)
1290 		tgtname = "";
1291 
1292 	/*
1293 	 * Resolve the types to their canonical form.
1294 	 */
1295 	(void) mdb_ctf_type_resolve(modid, &modid);
1296 	(void) mdb_ctf_type_resolve(tgtid, &tgtid);
1297 
1298 	if ((modkind = mdb_ctf_type_kind(modid)) == -1) {
1299 		mdb_ctf_warn(flags,
1300 		    "couldn't determine type kind of mdb module type %s\n",
1301 		    mdbtypename);
1302 		return (-1); /* errno is set for us */
1303 	}
1304 	if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) {
1305 		mdb_ctf_warn(flags,
1306 		    "couldn't determine type kind of %s\n", typename);
1307 		return (-1); /* errno is set for us */
1308 	}
1309 
1310 	if ((modsz = mdb_ctf_type_size(modid)) == -1UL) {
1311 		mdb_ctf_warn(flags, "couldn't determine type size of "
1312 		    "mdb module type %s\n", mdbtypename);
1313 		return (-1); /* errno is set for us */
1314 	}
1315 	if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) {
1316 		mdb_ctf_warn(flags, "couldn't determine size of %s (%s)\n",
1317 		    typename, tgtname);
1318 		return (-1); /* errno is set for us */
1319 	}
1320 
1321 	if (tgtkind == CTF_K_POINTER && modkind == CTF_K_INTEGER &&
1322 	    strcmp(mdbtypename, "uintptr_t") == 0) {
1323 		/* allow them to convert a pointer to a uintptr_t */
1324 		ASSERT(modsz == tgtsz);
1325 	} else if (tgtkind != modkind) {
1326 		mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n",
1327 		    typename, tgtname);
1328 		return (set_errno(EMDB_INCOMPAT));
1329 	}
1330 
1331 	switch (tgtkind) {
1332 	case CTF_K_INTEGER:
1333 	case CTF_K_FLOAT:
1334 		/*
1335 		 * Must determine if the target and module types have the same
1336 		 * encoding before we can copy them.
1337 		 */
1338 		if (mdb_ctf_type_encoding(tgtid, &tgt_encoding) != 0) {
1339 			mdb_ctf_warn(flags,
1340 			    "couldn't determine encoding of type %s (%s)\n",
1341 			    typename, tgtname);
1342 			return (-1); /* errno is set for us */
1343 		}
1344 		if (mdb_ctf_type_encoding(modid, &mod_encoding) != 0) {
1345 			mdb_ctf_warn(flags, "couldn't determine encoding of "
1346 			    "mdb module type %s\n", mdbtypename);
1347 			return (-1); /* errno is set for us */
1348 		}
1349 
1350 		if (modkind == CTF_K_INTEGER) {
1351 			if ((tgt_encoding.cte_format & CTF_INT_SIGNED) !=
1352 			    (mod_encoding.cte_format & CTF_INT_SIGNED)) {
1353 				mdb_ctf_warn(flags,
1354 				    "signedness mismatch between type "
1355 				    "%s (%s) and mdb module type %s\n",
1356 				    typename, tgtname, mdbtypename);
1357 				return (set_errno(EMDB_INCOMPAT));
1358 			}
1359 			signed_int =
1360 			    ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 0);
1361 		} else if (tgt_encoding.cte_format != mod_encoding.cte_format) {
1362 			mdb_ctf_warn(flags,
1363 			    "encoding mismatch (%#x != %#x) between type "
1364 			    "%s (%s) and mdb module type %s\n",
1365 			    tgt_encoding.cte_format, mod_encoding.cte_format,
1366 			    typename, tgtname, mdbtypename);
1367 			return (set_errno(EMDB_INCOMPAT));
1368 		}
1369 		/* FALLTHROUGH */
1370 	case CTF_K_POINTER:
1371 		/*
1372 		 * If the sizes don't match we need to be tricky to make
1373 		 * sure that the caller gets the correct data.
1374 		 */
1375 		if (modsz < tgtsz) {
1376 			mdb_ctf_warn(flags, "size of type %s (%s) is too "
1377 			    "large for mdb module type %s\n",
1378 			    typename, tgtname, mdbtypename);
1379 			return (set_errno(EMDB_INCOMPAT));
1380 		} else if (modsz > tgtsz) {
1381 			/* BEGIN CSTYLED */
1382 			/*
1383 			 * Fill modbuf with 1's for sign extension if target
1384 			 * buf is a signed integer and its value is negative.
1385 			 *
1386 			 *   S = sign bit (in most-significant byte)
1387 			 *
1388 			 *      BIG ENDIAN DATA
1389 			 *    +--------+--------+--------+--------+
1390 			 *    |S       |        |        |        |
1391 			 *    +--------+--------+--------+--------+
1392 			 *     0        1  ...            sz-1     sz
1393 			 *
1394 			 *      LITTLE ENDIAN DATA
1395 			 *    +--------+--------+--------+--------+
1396 			 *    |        |        |        |S       |
1397 			 *    +--------+--------+--------+--------+
1398 			 *     0        1  ...            sz-1     sz
1399 			 */
1400 			/* END CSTYLED */
1401 #ifdef _BIG_ENDIAN
1402 			if (signed_int && (tgtbuf[0] & 0x80) != 0)
1403 #else
1404 			if (signed_int && (tgtbuf[tgtsz - 1] & 0x80) != 0)
1405 #endif
1406 				(void) memset(modbuf, 0xFF, modsz);
1407 			else
1408 				bzero(modbuf, modsz);
1409 #ifdef _BIG_ENDIAN
1410 			bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz);
1411 #else
1412 			bcopy(tgtbuf, modbuf, tgtsz);
1413 #endif
1414 		} else {
1415 			bcopy(tgtbuf, modbuf, modsz);
1416 		}
1417 
1418 		return (0);
1419 
1420 	case CTF_K_ENUM:
1421 		if (modsz != tgtsz || modsz != sizeof (int)) {
1422 			mdb_ctf_warn(flags, "unexpected size of type %s (%s)\n",
1423 			    typename, tgtname);
1424 			return (set_errno(EMDB_INCOMPAT));
1425 		}
1426 
1427 		/*
1428 		 * Default to the same value as in the target.
1429 		 */
1430 		bcopy(tgtbuf, modbuf, sizeof (int));
1431 
1432 		/* LINTED */
1433 		i = *(int *)tgtbuf;
1434 
1435 		/* LINTED */
1436 		ev.ev_modbuf = (int *)modbuf;
1437 		ev.ev_name = mdb_ctf_enum_name(tgtid, i);
1438 		if (ev.ev_name == NULL) {
1439 			mdb_ctf_warn(flags,
1440 			    "unexpected value %u of enum type %s (%s)\n",
1441 			    i, typename, tgtname);
1442 			return (set_errno(EMDB_INCOMPAT));
1443 		}
1444 
1445 		ret = mdb_ctf_enum_iter(modid, enum_cb, &ev);
1446 		if (ret == 0) {
1447 			/* value not found */
1448 			mdb_ctf_warn(flags,
1449 			    "unexpected value %s (%u) of enum type %s (%s)\n",
1450 			    ev.ev_name, i, typename, tgtname);
1451 			return (set_errno(EMDB_INCOMPAT));
1452 		} else if (ret == 1) {
1453 			/* value found */
1454 			return (0);
1455 		} else if (ret == -1) {
1456 			mdb_ctf_warn(flags, "could not iterate enum %s (%s)\n",
1457 			    typename, tgtname);
1458 		}
1459 		return (ret);
1460 
1461 	case CTF_K_STRUCT:
1462 		mbr.m_modbuf = modbuf;
1463 		mbr.m_tgtbuf = tgtbuf;
1464 		mbr.m_tgtid = tgtid;
1465 		mbr.m_flags = flags;
1466 		mbr.m_tgtname = typename;
1467 
1468 		return (mdb_ctf_member_iter(modid, member_cb, &mbr));
1469 
1470 	case CTF_K_UNION:
1471 		mbr.m_modbuf = modbuf;
1472 		mbr.m_tgtbuf = tgtbuf;
1473 		mbr.m_tgtid = tgtid;
1474 		mbr.m_flags = flags;
1475 		mbr.m_tgtname = typename;
1476 
1477 		/*
1478 		 * Not all target union members need to be present in the
1479 		 * mdb type. If there is only a single union member in the
1480 		 * mdb type, its actual type does not need to match with
1481 		 * its target's type. On the other hand, if more than one
1482 		 * union members are specified in the mdb type, their types
1483 		 * must match with the types of their relevant union members
1484 		 * of the target union.
1485 		 */
1486 		mod_members = mdb_ctf_num_members(modid);
1487 		if (mod_members == 1) {
1488 			return (mdb_ctf_member_iter(modid, member_cb, &mbr));
1489 		} else if (mod_members > 1) {
1490 			if (mdb_ctf_member_iter(modid, type_equals_cb,
1491 			    &tgtid)) {
1492 				mdb_ctf_warn(flags,
1493 				    "inexact match for union %s (%s)\n",
1494 				    typename, tgtname);
1495 				return (set_errno(EMDB_INCOMPAT));
1496 			}
1497 
1498 			/*
1499 			 * From the check above we know that the members
1500 			 * which are present in the mdb type are equal to
1501 			 * the types in the target. Thus, the member_cb
1502 			 * callback below will not move anything around and
1503 			 * it is equivalent to:
1504 			 *
1505 			 * bcopy(tgtbuf, modbuf, MAX(module member's sizes))
1506 			 */
1507 			return (mdb_ctf_member_iter(modid, member_cb, &mbr));
1508 		} else {
1509 			/*
1510 			 * We either got 0 or -1. In any case that number
1511 			 * should be returned right away. For the error
1512 			 * case of -1, errno has been set for us.
1513 			 */
1514 			return (mod_members);
1515 		}
1516 
1517 	case CTF_K_ARRAY:
1518 		if (mdb_ctf_array_info(tgtid, &tar) != 0) {
1519 			mdb_ctf_warn(flags,
1520 			    "couldn't get array info for %s (%s)\n",
1521 			    typename, tgtname);
1522 			return (-1); /* errno is set for us */
1523 		}
1524 		if (mdb_ctf_array_info(modid, &mar) != 0) {
1525 			mdb_ctf_warn(flags,
1526 			    "couldn't get array info for mdb module type %s\n",
1527 			    mdbtypename);
1528 			return (-1); /* errno is set for us */
1529 		}
1530 
1531 		if (tar.mta_nelems != mar.mta_nelems) {
1532 			mdb_ctf_warn(flags,
1533 			    "unexpected array size (%u) for type %s (%s)\n",
1534 			    tar.mta_nelems, typename, tgtname);
1535 			return (set_errno(EMDB_INCOMPAT));
1536 		}
1537 
1538 		if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) {
1539 			mdb_ctf_warn(flags, "couldn't determine type size of "
1540 			    "mdb module type %s\n", mdbtypename);
1541 			return (-1); /* errno is set for us */
1542 		}
1543 		if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) {
1544 			mdb_ctf_warn(flags,
1545 			    "couldn't determine size of %s (%s)\n",
1546 			    typename, tgtname);
1547 			return (-1); /* errno is set for us */
1548 		}
1549 
1550 		for (i = 0; i < tar.mta_nelems; i++) {
1551 			ret = vread_helper(mar.mta_contents, modbuf + i * modsz,
1552 			    tar.mta_contents, tgtbuf + i * tgtsz,
1553 			    tgtname, flags);
1554 
1555 			if (ret != 0)
1556 				return (ret);
1557 		}
1558 
1559 		return (0);
1560 	}
1561 
1562 	mdb_ctf_warn(flags, "unsupported kind %d for type %s (%s)\n",
1563 	    modkind, typename, tgtname);
1564 	return (set_errno(EMDB_INCOMPAT));
1565 }
1566 
1567 /*
1568  * Like mdb_vread(), mdb_ctf_vread() is used to read from the target's
1569  * virtual address space.  However, mdb_ctf_vread() can be used to safely
1570  * read a complex type (e.g. a struct) from the target, even if MDB was compiled
1571  * against a different definition of that type (e.g. when debugging a crash
1572  * dump from an older release).
1573  *
1574  * Callers can achieve this by defining their own type which corresponds to the
1575  * type in the target, but contains only the members that the caller requires.
1576  * Using the CTF type information embedded in the target, mdb_ctf_vread will
1577  * find the required members in the target and fill in the caller's structure.
1578  * The members are located by name, and their types are verified to be
1579  * compatible.
1580  *
1581  * By convention, the caller will declare a type with the name "mdb_<type>",
1582  * where <type> is the name of the type in the target (e.g. mdb_zio_t).  This
1583  * type will contain the members that the caller is interested in.  For example:
1584  *
1585  * typedef struct mdb_zio {
1586  *         enum zio_type io_type;
1587  *         uintptr_t io_waiter;
1588  *         struct {
1589  *                 struct {
1590  *                         uintptr_t list_next;
1591  *                 } list_head;
1592  *         } io_parent_list;
1593  *         int io_error;
1594  * } mdb_zio_t;
1595  *
1596  * mdb_zio_t zio;
1597  * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0);
1598  *
1599  * If a given MDB module has different dcmds or walkers that need to read
1600  * different members from the same struct, then different "mdb_" types
1601  * should be declared for each caller.  By convention, these types should
1602  * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t
1603  * for ::findstack.  If the MDB module is compiled from several source files,
1604  * one must be especially careful to not define different types with the
1605  * same name in different source files, because the compiler can not detect
1606  * this error.
1607  *
1608  * Enums will also be translated by name, so the mdb module will receive
1609  * the enum value it expects even if the target has renumbered the enum.
1610  * Warning: it will therefore only work with enums are only used to store
1611  * legitimate enum values (not several values or-ed together).
1612  *
1613  * By default, if mdb_ctf_vread() can not find any members or enum values,
1614  * it will print a descriptive message (with mdb_warn()) and fail.
1615  * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message.
1616  * Additional flags can be used to ignore specific types of translation
1617  * failure, but should be used with caution, because they will silently leave
1618  * the caller's buffer uninitialized.
1619  */
1620 int
1621 mdb_ctf_vread(void *modbuf, const char *target_typename,
1622     const char *mdb_typename, uintptr_t addr, uint_t flags)
1623 {
1624 	ctf_file_t *mfp;
1625 	ctf_id_t mid;
1626 	void *tgtbuf;
1627 	size_t size;
1628 	mdb_ctf_id_t tgtid;
1629 	mdb_ctf_id_t modid;
1630 	mdb_module_t *mod;
1631 
1632 	if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
1633 		mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
1634 		    mod->mod_name);
1635 		return (set_errno(EMDB_NOCTF));
1636 	}
1637 
1638 	if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) {
1639 		mdb_ctf_warn(flags, "couldn't find ctf data for "
1640 		    "type %s in mdb module %s\n",
1641 		    mdb_typename, mod->mod_name);
1642 		return (set_errno(ctf_to_errno(ctf_errno(mfp))));
1643 	}
1644 
1645 	set_ctf_id(&modid, mfp, mid);
1646 
1647 	if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) {
1648 		mdb_ctf_warn(flags,
1649 		    "couldn't find type %s in target's ctf data\n",
1650 		    target_typename);
1651 		return (set_errno(EMDB_NOCTF));
1652 	}
1653 
1654 	/*
1655 	 * Read the data out of the target's address space.
1656 	 */
1657 	if ((size = mdb_ctf_type_size(tgtid)) == -1UL) {
1658 		mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
1659 		    target_typename);
1660 		return (-1); /* errno is set for us */
1661 	}
1662 
1663 	tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
1664 
1665 	if (mdb_vread(tgtbuf, size, addr) < 0) {
1666 		mdb_ctf_warn(flags, "couldn't read %s from %p\n",
1667 		    target_typename, addr);
1668 		return (-1); /* errno is set for us */
1669 	}
1670 
1671 	return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags));
1672 }
1673 
1674 /*
1675  * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
1676  * of the target's type vs the mdb module's type.  Use with complicated
1677  * types (e.g. structs) may result in unnecessary failure if a member of
1678  * the struct has been changed in the target, but is not actually needed
1679  * by the mdb module.  Use mdb_lookup_by_name() + mdb_ctf_vread() to
1680  * avoid this problem.
1681  */
1682 int
1683 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
1684 {
1685 	GElf_Sym sym;
1686 
1687 	if (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, name, &sym) != 0) {
1688 		mdb_ctf_warn(flags, "couldn't find symbol %s\n", name);
1689 		return (-1); /* errno is set for us */
1690 	}
1691 
1692 	return (mdb_ctf_vread(buf, typename, typename, sym.st_value, flags));
1693 }
1694 
1695 ctf_file_t *
1696 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va,
1697     Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp)
1698 {
1699 	ctf_sect_t ctdata, symtab, strtab;
1700 
1701 	ctdata.cts_name = ".SUNW_ctf";
1702 	ctdata.cts_type = SHT_PROGBITS;
1703 	ctdata.cts_flags = 0;
1704 	ctdata.cts_data = ctf_va;
1705 	ctdata.cts_size = ctf_size;
1706 	ctdata.cts_entsize = 1;
1707 	ctdata.cts_offset = 0;
1708 
1709 	symtab.cts_name = ".symtab";
1710 	symtab.cts_type = symhdr->sh_type;
1711 	symtab.cts_flags = symhdr->sh_flags;
1712 	symtab.cts_data = sym_va;
1713 	symtab.cts_size = symhdr->sh_size;
1714 	symtab.cts_entsize = symhdr->sh_entsize;
1715 	symtab.cts_offset = symhdr->sh_offset;
1716 
1717 	strtab.cts_name = ".strtab";
1718 	strtab.cts_type = strhdr->sh_type;
1719 	strtab.cts_flags = strhdr->sh_flags;
1720 	strtab.cts_data = str_va;
1721 	strtab.cts_size = strhdr->sh_size;
1722 	strtab.cts_entsize = strhdr->sh_entsize;
1723 	strtab.cts_offset = strhdr->sh_offset;
1724 
1725 	return (ctf_bufopen(&ctdata, &symtab, &strtab, errp));
1726 }
1727 
1728 int
1729 mdb_ctf_synthetics_init(void)
1730 {
1731 	int err;
1732 
1733 	if ((mdb.m_synth = ctf_create(&err)) == NULL)
1734 		return (set_errno(ctf_to_errno(err)));
1735 
1736 	return (0);
1737 }
1738 
1739 void
1740 mdb_ctf_synthetics_fini(void)
1741 {
1742 	if (mdb.m_synth == NULL)
1743 		return;
1744 
1745 	ctf_close(mdb.m_synth);
1746 	mdb.m_synth = NULL;
1747 }
1748 
1749 int
1750 mdb_ctf_synthetics_create_base(int kind)
1751 {
1752 	const synth_intrinsic_t *synp;
1753 	const synth_typedef_t *sytp;
1754 	int err;
1755 	ctf_id_t id;
1756 	ctf_file_t *cp = mdb.m_synth;
1757 
1758 	if (mdb.m_synth == NULL) {
1759 		mdb_printf("synthetic types disabled: ctf create failed\n");
1760 		return (1);
1761 	}
1762 
1763 	switch (kind) {
1764 	case SYNTHETIC_ILP32:
1765 		synp = synth_builtins32;
1766 		sytp = synth_typedefs32;
1767 		break;
1768 	case SYNTHETIC_LP64:
1769 		synp = synth_builtins64;
1770 		sytp = synth_typedefs64;
1771 		break;
1772 	default:
1773 		mdb_dprintf(MDB_DBG_CTF, "invalid type of intrinsic: %d\n",
1774 		    kind);
1775 		return (1);
1776 	}
1777 
1778 	err = 0;
1779 	for (; synp->syn_name != NULL; synp++) {
1780 		if (synp->syn_kind == CTF_K_INTEGER) {
1781 			err = ctf_add_integer(cp, CTF_ADD_ROOT, synp->syn_name,
1782 			    &synp->syn_enc);
1783 		} else {
1784 			err = ctf_add_float(cp, CTF_ADD_ROOT, synp->syn_name,
1785 			    &synp->syn_enc);
1786 		}
1787 
1788 		if (err == CTF_ERR) {
1789 			mdb_dprintf(MDB_DBG_CTF, "couldn't add synthetic "
1790 			    "type: %s\n", synp->syn_name);
1791 			goto discard;
1792 		}
1793 	}
1794 
1795 	if (ctf_update(cp) == CTF_ERR) {
1796 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
1797 		goto discard;
1798 	}
1799 
1800 	for (; sytp->syt_src != NULL; sytp++) {
1801 		id = ctf_lookup_by_name(cp, sytp->syt_src);
1802 		if (id == CTF_ERR) {
1803 			mdb_dprintf(MDB_DBG_CTF, "cailed to lookup %s: %s\n",
1804 			    sytp->syt_src, ctf_errmsg(ctf_errno(cp)));
1805 			goto discard;
1806 		}
1807 		if (ctf_add_typedef(cp, CTF_ADD_ROOT, sytp->syt_targ, id) ==
1808 		    CTF_ERR) {
1809 			mdb_dprintf(MDB_DBG_CTF, "couldn't add typedef %s "
1810 			    "%s: %s\n", sytp->syt_targ, sytp->syt_src,
1811 			    ctf_errmsg(ctf_errno(cp)));
1812 			goto discard;
1813 		}
1814 	}
1815 
1816 	if (ctf_update(cp) == CTF_ERR) {
1817 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
1818 		goto discard;
1819 	}
1820 
1821 	return (0);
1822 
1823 discard:
1824 	err = set_errno(ctf_to_errno(ctf_errno(cp)));
1825 	(void) ctf_discard(cp);
1826 	return (err);
1827 }
1828 
1829 int
1830 mdb_ctf_synthetics_reset(void)
1831 {
1832 	mdb_ctf_synthetics_fini();
1833 	return (mdb_ctf_synthetics_init());
1834 }
1835 
1836 int
1837 mdb_ctf_add_typedef(const char *name, const mdb_ctf_id_t *p, mdb_ctf_id_t *new)
1838 {
1839 	ctf_id_t rid;
1840 	mdb_ctf_id_t tid;
1841 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
1842 
1843 	if (mdb.m_synth == NULL) {
1844 		mdb_printf("synthetic types disabled: ctf create failed\n");
1845 		return (1);
1846 	}
1847 
1848 	if (mdb_ctf_lookup_by_name(name, &tid) == 0) {
1849 		mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1850 		    "with that name already exists\n", name);
1851 		return (set_errno(EEXIST));
1852 	}
1853 
1854 	rid = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
1855 	if (rid == CTF_ERR) {
1856 		mdb_dprintf(MDB_DBG_CTF, "failed to add reference type: %s\n",
1857 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1858 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1859 	}
1860 	rid = ctf_add_typedef(mdb.m_synth, CTF_ADD_ROOT, name, rid);
1861 	if (rid == CTF_ERR) {
1862 		mdb_dprintf(MDB_DBG_CTF, "failed to add typedef: %s",
1863 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1864 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1865 	}
1866 
1867 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
1868 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1869 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1870 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1871 	}
1872 
1873 	if (new != NULL)
1874 		set_ctf_id(new, mdb.m_synth, rid);
1875 
1876 	return (0);
1877 }
1878 
1879 int
1880 mdb_ctf_add_struct(const char *name, mdb_ctf_id_t *rid)
1881 {
1882 	mdb_ctf_id_t tid;
1883 	ctf_id_t id;
1884 
1885 	if (mdb.m_synth == NULL) {
1886 		mdb_printf("synthetic types disabled: ctf create failed\n");
1887 		return (1);
1888 	}
1889 
1890 	if (name != NULL && mdb_ctf_lookup_by_name(name, &tid) == 0) {
1891 		mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1892 		    "with that name already exists\n", name);
1893 		return (set_errno(EEXIST));
1894 	}
1895 
1896 	if ((id = ctf_add_struct(mdb.m_synth, CTF_ADD_ROOT, name)) ==
1897 	    CTF_ERR) {
1898 		mdb_dprintf(MDB_DBG_CTF, "failed to add struct: %s\n",
1899 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1900 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1901 	}
1902 
1903 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
1904 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1905 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1906 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1907 	}
1908 
1909 	if (rid != NULL)
1910 		set_ctf_id(rid, mdb.m_synth, id);
1911 
1912 	return (0);
1913 }
1914 
1915 int
1916 mdb_ctf_add_union(const char *name, mdb_ctf_id_t *rid)
1917 {
1918 	mdb_ctf_id_t tid;
1919 	ctf_id_t id;
1920 
1921 	if (mdb.m_synth == NULL) {
1922 		mdb_printf("synthetic types disabled: ctf create failed\n");
1923 		return (1);
1924 	}
1925 
1926 	if (name != NULL && mdb_ctf_lookup_by_name(name, &tid) == 0) {
1927 		mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1928 		    "with that name already exists\n", name);
1929 		return (set_errno(EEXIST));
1930 	}
1931 
1932 	if ((id = ctf_add_union(mdb.m_synth, CTF_ADD_ROOT, name)) ==
1933 	    CTF_ERR) {
1934 		mdb_dprintf(MDB_DBG_CTF, "failed to add union: %s\n",
1935 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1936 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1937 	}
1938 
1939 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
1940 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1941 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1942 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1943 	}
1944 
1945 	if (rid != NULL)
1946 		set_ctf_id(rid, mdb.m_synth, id);
1947 
1948 	return (0);
1949 }
1950 
1951 int
1952 mdb_ctf_add_member(const mdb_ctf_id_t *p, const char *name,
1953     const mdb_ctf_id_t *mtype, mdb_ctf_id_t *rid)
1954 {
1955 	ctf_id_t id, mtid;
1956 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
1957 	mdb_ctf_impl_t *mcim = (mdb_ctf_impl_t *)mtype;
1958 
1959 	if (mdb.m_synth == NULL) {
1960 		mdb_printf("synthetic types disabled: ctf create failed\n");
1961 		return (DCMD_ERR);
1962 	}
1963 
1964 	if (mcip->mci_fp != mdb.m_synth) {
1965 		mdb_dprintf(MDB_DBG_CTF, "requested to add member to a type "
1966 		    "that wasn't created from a synthetic\n");
1967 		return (set_errno(EINVAL));
1968 	}
1969 
1970 	mtid = ctf_add_type(mdb.m_synth, mcim->mci_fp, mcim->mci_id);
1971 	if (mtid == CTF_ERR) {
1972 		mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
1973 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1974 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1975 	}
1976 
1977 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
1978 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1979 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1980 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1981 	}
1982 
1983 	id = ctf_add_member(mdb.m_synth, mcip->mci_id, name, mtid);
1984 	if (id == CTF_ERR) {
1985 		mdb_dprintf(MDB_DBG_CTF, "failed to add member %s: %s\n",
1986 		    name, ctf_errmsg(ctf_errno(mdb.m_synth)));
1987 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1988 	}
1989 
1990 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
1991 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1992 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
1993 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1994 	}
1995 
1996 	if (rid != NULL)
1997 		set_ctf_id(rid, mdb.m_synth, id);
1998 
1999 	return (0);
2000 }
2001 
2002 int
2003 mdb_ctf_add_array(const mdb_ctf_arinfo_t *marp, mdb_ctf_id_t *rid)
2004 {
2005 	mdb_ctf_impl_t *mcip;
2006 	ctf_arinfo_t car;
2007 	ctf_id_t id;
2008 
2009 	if (mdb.m_synth == NULL) {
2010 		mdb_printf("synthetic types disabled: ctf create failed\n");
2011 		return (1);
2012 	}
2013 
2014 	car.ctr_nelems = marp->mta_nelems;
2015 
2016 	mcip = (mdb_ctf_impl_t *)&marp->mta_contents;
2017 	id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2018 	if (id == CTF_ERR) {
2019 		mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
2020 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2021 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2022 	}
2023 	car.ctr_contents = id;
2024 
2025 	mcip = (mdb_ctf_impl_t *)&marp->mta_index;
2026 	id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2027 	if (id == CTF_ERR) {
2028 		mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
2029 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2030 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2031 	}
2032 	car.ctr_index = id;
2033 
2034 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
2035 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2036 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2037 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2038 	}
2039 
2040 	id = ctf_add_array(mdb.m_synth, CTF_ADD_ROOT, &car);
2041 	if (id == CTF_ERR) {
2042 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2043 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2044 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2045 	}
2046 
2047 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
2048 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2049 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2050 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2051 	}
2052 
2053 	if (rid != NULL)
2054 		set_ctf_id(rid, mdb.m_synth, id);
2055 
2056 	return (0);
2057 }
2058 
2059 int
2060 mdb_ctf_add_pointer(const mdb_ctf_id_t *p, mdb_ctf_id_t *rid)
2061 {
2062 	ctf_id_t id;
2063 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
2064 
2065 	if (mdb.m_synth == NULL) {
2066 		mdb_printf("synthetic types disabled: ctf create failed\n");
2067 		return (1);
2068 	}
2069 
2070 	id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2071 	if (id == CTF_ERR) {
2072 		mdb_dprintf(MDB_DBG_CTF, "failed to add pointer type: %s\n",
2073 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2074 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2075 	}
2076 
2077 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
2078 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2079 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2080 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2081 	}
2082 
2083 
2084 	id = ctf_add_pointer(mdb.m_synth, CTF_ADD_ROOT, id);
2085 	if (id == CTF_ERR) {
2086 		mdb_dprintf(MDB_DBG_CTF, "failed to add pointer: %s\n",
2087 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2088 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2089 	}
2090 
2091 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
2092 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2093 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2094 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2095 	}
2096 
2097 
2098 	if (rid != NULL)
2099 		set_ctf_id(rid, mdb.m_synth, id);
2100 
2101 	return (0);
2102 }
2103 
2104 int
2105 mdb_ctf_type_delete(const mdb_ctf_id_t *id)
2106 {
2107 	int ret;
2108 
2109 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)id;
2110 
2111 	if (mcip->mci_fp != mdb.m_synth) {
2112 		mdb_warn("bad ctf_file_t, expected synth container\n");
2113 		return (1);
2114 	}
2115 
2116 	ret = ctf_delete_type(mcip->mci_fp, mcip->mci_id);
2117 	if (ret != 0) {
2118 		mdb_dprintf(MDB_DBG_CTF, "failed to delete synthetic type: %s",
2119 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2120 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2121 	}
2122 
2123 	if (ctf_update(mdb.m_synth) == CTF_ERR) {
2124 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2125 		    ctf_errmsg(ctf_errno(mdb.m_synth)));
2126 		return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2127 	}
2128 
2129 	return (0);
2130 }
2131 
2132 static int
2133 mdb_ctf_synthetics_file_cb(mdb_ctf_id_t id, void *arg)
2134 {
2135 	ctf_file_t *targ = arg;
2136 	mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)&id;
2137 
2138 	if (ctf_add_type(targ, mcip->mci_fp, mcip->mci_id) == CTF_ERR) {
2139 		mdb_dprintf(MDB_DBG_CTF, "failed to add type %d: %s\n",
2140 		    mcip->mci_id, ctf_errmsg(ctf_errno(mcip->mci_fp)));
2141 		return (set_errno(ctf_to_errno(ctf_errno(mcip->mci_fp))));
2142 	}
2143 
2144 	return (0);
2145 }
2146 
2147 int
2148 mdb_ctf_synthetics_from_file(const char *file)
2149 {
2150 	ctf_file_t *fp, *syn = mdb.m_synth;
2151 	int ret;
2152 	type_iter_t ti;
2153 
2154 	if (syn == NULL) {
2155 		mdb_warn("synthetic types disabled: ctf create failed\n");
2156 		return (1);
2157 	}
2158 
2159 	if ((fp = mdb_ctf_open(file, &ret)) == NULL) {
2160 		mdb_warn("failed to parse ctf data in %s: %s\n", file,
2161 		    ctf_errmsg(ret));
2162 		return (1);
2163 	}
2164 
2165 	ret = DCMD_OK;
2166 	ti.ti_fp = fp;
2167 	ti.ti_arg = syn;
2168 	ti.ti_cb = mdb_ctf_synthetics_file_cb;
2169 	if (ctf_type_iter(fp, type_iter_cb, &ti) == CTF_ERR) {
2170 		ret = set_errno(ctf_to_errno(ctf_errno(fp)));
2171 		mdb_warn("failed to add types");
2172 		goto cleanup;
2173 	}
2174 
2175 	if (ctf_update(syn) == CTF_ERR) {
2176 		mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
2177 		ret = set_errno(ctf_to_errno(ctf_errno(fp)));
2178 	}
2179 
2180 cleanup:
2181 	ctf_close(fp);
2182 	if (ret != 0)
2183 		(void) ctf_discard(syn);
2184 	return (ret);
2185 }
2186 
2187 int
2188 mdb_ctf_synthetics_to_file(const char *file)
2189 {
2190 	int err;
2191 	ctf_file_t *fp = mdb.m_synth;
2192 
2193 	if (fp == NULL) {
2194 		mdb_warn("synthetic types are disabled, not writing "
2195 		    "anything\n");
2196 		return (DCMD_ERR);
2197 	}
2198 
2199 	err = mdb_ctf_write(file, fp);
2200 	if (err != 0) {
2201 		if (err == CTF_ERR)
2202 			(void) set_errno(ctf_to_errno(ctf_errno(fp)));
2203 		else
2204 			(void) set_errno(err);
2205 		err = DCMD_ERR;
2206 	} else {
2207 		err = DCMD_OK;
2208 	}
2209 
2210 	return (err);
2211 }
2212