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