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