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 *)∣
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_lname(mdb_ctf_id_t id,char * buf,size_t len)576 mdb_ctf_type_lname(mdb_ctf_id_t id, char *buf, size_t len)
577 {
578 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
579 char *ret;
580
581 if (!mdb_ctf_type_valid(id))
582 return (set_errno(EINVAL));
583
584 return (ctf_type_lname(idp->mci_fp, idp->mci_id, buf, len));
585 }
586
587 ssize_t
mdb_ctf_type_size(mdb_ctf_id_t id)588 mdb_ctf_type_size(mdb_ctf_id_t id)
589 {
590 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
591 ssize_t ret;
592
593 /* resolve the type in case there's a forward declaration */
594 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
595 return (ret);
596
597 if ((ret = ctf_type_size(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_kind(mdb_ctf_id_t id)604 mdb_ctf_type_kind(mdb_ctf_id_t id)
605 {
606 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
607 int ret;
608
609 if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR)
610 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
611
612 return (ret);
613 }
614
615 int
mdb_ctf_type_reference(mdb_ctf_id_t mid,mdb_ctf_id_t * outp)616 mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
617 {
618 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣
619 ctf_id_t id;
620
621 if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
622 if (outp)
623 mdb_ctf_type_invalidate(outp);
624 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
625 }
626
627 if (outp != NULL)
628 set_ctf_id(outp, idp->mci_fp, id);
629
630 return (0);
631 }
632
633
634 int
mdb_ctf_type_encoding(mdb_ctf_id_t id,ctf_encoding_t * ep)635 mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep)
636 {
637 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
638
639 if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR)
640 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
641
642 return (0);
643 }
644
645 /*
646 * callback proxy for mdb_ctf_type_visit
647 */
648 static int
type_cb(const char * name,ctf_id_t type,ulong_t off,int depth,void * arg)649 type_cb(const char *name, ctf_id_t type, ulong_t off, int depth, void *arg)
650 {
651 type_visit_t *tvp = arg;
652 mdb_ctf_id_t id;
653 mdb_ctf_id_t base;
654 mdb_ctf_impl_t *basep = (mdb_ctf_impl_t *)&base;
655
656 int ret;
657
658 if (depth < tvp->tv_min_depth)
659 return (0);
660
661 off += tvp->tv_base_offset;
662 depth += tvp->tv_base_depth;
663
664 set_ctf_id(&id, tvp->tv_fp, type);
665
666 (void) mdb_ctf_type_resolve(id, &base);
667 if ((ret = tvp->tv_cb(name, id, base, off, depth, tvp->tv_arg)) != 0)
668 return (ret);
669
670 /*
671 * If the type resolves to a type in a different file, we must have
672 * followed a forward declaration. We need to recurse into the
673 * new type.
674 */
675 if (basep->mci_fp != tvp->tv_fp && mdb_ctf_type_valid(base)) {
676 type_visit_t tv;
677
678 tv.tv_cb = tvp->tv_cb;
679 tv.tv_arg = tvp->tv_arg;
680 tv.tv_fp = basep->mci_fp;
681
682 tv.tv_base_offset = off;
683 tv.tv_base_depth = depth;
684 tv.tv_min_depth = 1; /* depth = 0 has already been done */
685
686 ret = ctf_type_visit(basep->mci_fp, basep->mci_id,
687 type_cb, &tv);
688 }
689 return (ret);
690 }
691
692 int
mdb_ctf_type_visit(mdb_ctf_id_t id,mdb_ctf_visit_f * func,void * arg)693 mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg)
694 {
695 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
696 type_visit_t tv;
697 int ret;
698
699 tv.tv_cb = func;
700 tv.tv_arg = arg;
701 tv.tv_fp = idp->mci_fp;
702 tv.tv_base_offset = 0;
703 tv.tv_base_depth = 0;
704 tv.tv_min_depth = 0;
705
706 ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv);
707
708 if (ret == CTF_ERR)
709 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
710
711 return (ret);
712 }
713
714 int
mdb_ctf_array_info(mdb_ctf_id_t id,mdb_ctf_arinfo_t * arp)715 mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp)
716 {
717 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
718 ctf_arinfo_t car;
719
720 if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR)
721 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
722
723 set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents);
724 set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index);
725
726 arp->mta_nelems = car.ctr_nelems;
727
728 return (0);
729 }
730
731 const char *
mdb_ctf_enum_name(mdb_ctf_id_t id,int value)732 mdb_ctf_enum_name(mdb_ctf_id_t id, int value)
733 {
734 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
735 const char *ret;
736
737 /* resolve the type in case there's a forward declaration */
738 if (mdb_ctf_type_resolve(id, &id) != 0)
739 return (NULL);
740
741 if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL)
742 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
743
744 return (ret);
745 }
746
747 /*
748 * callback proxy for mdb_ctf_member_iter
749 */
750 static int
member_iter_cb(const char * name,ctf_id_t type,ulong_t off,void * data)751 member_iter_cb(const char *name, ctf_id_t type, ulong_t off, void *data)
752 {
753 int ret, kind;
754 member_iter_t *mip = data;
755 mdb_ctf_id_t id;
756
757 set_ctf_id(&id, mip->mi_fp, type);
758
759 ret = mip->mi_cb(name, id, mip->mi_off + off, mip->mi_arg);
760 if (ret != 0) {
761 return (ret);
762 }
763
764 /*
765 * If we have an anonymous struct or union and we've been asked to
766 * process it, recurse through it. We need to modify the offset that
767 * we're at as we progress through this so that way the caller sees this
768 * at the correct memory location.
769 */
770 kind = ctf_type_kind(mip->mi_fp, type);
771 if ((kind == CTF_K_STRUCT || kind == CTF_K_UNION) && *name == '\0' &&
772 (mip->mi_flags & MDB_CTF_F_ITER_ANON) != 0) {
773 mip->mi_off += off;
774 ret = ctf_member_iter(mip->mi_fp, type, member_iter_cb, mip);
775 mip->mi_off -= off;
776 }
777
778 return (ret);
779 }
780
781 int
mdb_ctf_member_iter(mdb_ctf_id_t id,mdb_ctf_member_f * cb,void * data,uint32_t flags)782 mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data,
783 uint32_t flags)
784 {
785 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
786 member_iter_t mi;
787 int ret;
788
789 if ((flags & ~MDB_CTF_F_ITER_ANON) != 0) {
790 return (set_errno(EINVAL));
791 }
792
793 /* resolve the type in case there's a forward declaration */
794 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
795 return (ret);
796
797 mi.mi_cb = cb;
798 mi.mi_arg = data;
799 mi.mi_fp = idp->mci_fp;
800 mi.mi_flags = flags;
801 mi.mi_off = 0;
802
803 ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi);
804
805 if (ret == CTF_ERR)
806 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
807
808 return (ret);
809 }
810
811 int
mdb_ctf_enum_iter(mdb_ctf_id_t id,mdb_ctf_enum_f * cb,void * data)812 mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data)
813 {
814 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
815 int ret;
816
817 /* resolve the type in case there's a forward declaration */
818 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
819 return (ret);
820
821 return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data));
822 }
823
824 /*
825 * callback proxy for mdb_ctf_type_iter
826 */
827 /* ARGSUSED */
828 static int
type_iter_cb(ctf_id_t type,boolean_t root,void * data)829 type_iter_cb(ctf_id_t type, boolean_t root, void *data)
830 {
831 type_iter_t *tip = data;
832 mdb_ctf_id_t id;
833
834 set_ctf_id(&id, tip->ti_fp, type);
835
836 return (tip->ti_cb(id, tip->ti_arg));
837 }
838
839 int
mdb_ctf_type_iter(const char * object,mdb_ctf_type_f * cb,void * data)840 mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data)
841 {
842 ctf_file_t *fp;
843 mdb_tgt_t *t = mdb.m_target;
844 int ret;
845 type_iter_t ti;
846
847 if (object == MDB_CTF_SYNTHETIC_ITER)
848 fp = mdb.m_synth;
849 else
850 fp = mdb_tgt_name_to_ctf(t, object);
851
852 if (fp == NULL)
853 return (-1);
854
855 ti.ti_cb = cb;
856 ti.ti_arg = data;
857 ti.ti_fp = fp;
858
859 if ((ret = ctf_type_iter(fp, B_FALSE, type_iter_cb, &ti)) == CTF_ERR)
860 return (set_errno(ctf_to_errno(ctf_errno(fp))));
861
862 return (ret);
863 }
864
865 /* utility functions */
866
867 ctf_id_t
mdb_ctf_type_id(mdb_ctf_id_t id)868 mdb_ctf_type_id(mdb_ctf_id_t id)
869 {
870 return (((mdb_ctf_impl_t *)&id)->mci_id);
871 }
872
873 ctf_file_t *
mdb_ctf_type_file(mdb_ctf_id_t id)874 mdb_ctf_type_file(mdb_ctf_id_t id)
875 {
876 return (((mdb_ctf_impl_t *)&id)->mci_fp);
877 }
878
879 static int
member_info_cb(const char * name,mdb_ctf_id_t id,ulong_t off,void * data)880 member_info_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
881 {
882 mbr_info_t *mbrp = data;
883
884 if (strcmp(name, mbrp->mbr_member) == 0) {
885 if (mbrp->mbr_offp != NULL)
886 *(mbrp->mbr_offp) = off;
887 if (mbrp->mbr_typep != NULL)
888 *(mbrp->mbr_typep) = id;
889
890 return (1);
891 }
892
893 return (0);
894 }
895
896 int
mdb_ctf_member_info(mdb_ctf_id_t id,const char * member,ulong_t * offp,mdb_ctf_id_t * typep)897 mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp,
898 mdb_ctf_id_t *typep)
899 {
900 mbr_info_t mbr;
901 int rc;
902
903 mbr.mbr_member = member;
904 mbr.mbr_offp = offp;
905 mbr.mbr_typep = typep;
906
907 rc = mdb_ctf_member_iter(id, member_info_cb, &mbr, MDB_CTF_F_ITER_ANON);
908
909 /* couldn't get member list */
910 if (rc == -1)
911 return (-1); /* errno is set for us */
912
913 /* not a member */
914 if (rc == 0)
915 return (set_errno(EMDB_CTFNOMEMB));
916
917 return (0);
918 }
919
920 /*
921 * Returns offset in _bits_ in *retp.
922 */
923 int
mdb_ctf_offsetof(mdb_ctf_id_t id,const char * member,ulong_t * retp)924 mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp)
925 {
926 return (mdb_ctf_member_info(id, member, retp, NULL));
927 }
928
929 /*
930 * Returns offset in _bytes_, or -1 on failure.
931 */
932 int
mdb_ctf_offsetof_by_name(const char * type,const char * member)933 mdb_ctf_offsetof_by_name(const char *type, const char *member)
934 {
935 mdb_ctf_id_t id;
936 ulong_t off;
937
938 if (mdb_ctf_lookup_by_name(type, &id) == -1) {
939 mdb_warn("couldn't find type %s", type);
940 return (-1);
941 }
942
943 if (mdb_ctf_offsetof(id, member, &off) == -1) {
944 mdb_warn("couldn't find member %s of type %s", member, type);
945 return (-1);
946 }
947 if (off % 8 != 0) {
948 mdb_warn("member %s of type %s is an unsupported bitfield\n",
949 member, type);
950 return (-1);
951 }
952 off /= 8;
953
954 return (off);
955 }
956
957 ssize_t
mdb_ctf_sizeof_by_name(const char * type)958 mdb_ctf_sizeof_by_name(const char *type)
959 {
960 mdb_ctf_id_t id;
961 ssize_t size;
962
963 if (mdb_ctf_lookup_by_name(type, &id) == -1) {
964 mdb_warn("couldn't find type %s", type);
965 return (-1);
966 }
967
968 if ((size = mdb_ctf_type_size(id)) == -1) {
969 mdb_warn("couldn't determine type size of %s", type);
970 return (-1);
971 }
972
973 return (size);
974 }
975
976 /*ARGSUSED*/
977 static int
num_members_cb(const char * name,mdb_ctf_id_t id,ulong_t off,void * data)978 num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
979 {
980 int *count = data;
981 *count = *count + 1;
982 return (0);
983 }
984
985 int
mdb_ctf_num_members(mdb_ctf_id_t id)986 mdb_ctf_num_members(mdb_ctf_id_t id)
987 {
988 int count = 0;
989
990 if (mdb_ctf_member_iter(id, num_members_cb, &count, 0) != 0)
991 return (-1); /* errno is set for us */
992
993 return (count);
994 }
995
996 typedef struct mbr_contains {
997 char **mbc_bufp;
998 size_t *mbc_lenp;
999 ulong_t *mbc_offp;
1000 mdb_ctf_id_t *mbc_idp;
1001 ssize_t mbc_total;
1002 } mbr_contains_t;
1003
1004 static int
offset_to_name_cb(const char * name,mdb_ctf_id_t id,ulong_t off,void * data)1005 offset_to_name_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
1006 {
1007 mbr_contains_t *mbc = data;
1008 ulong_t size;
1009 ctf_encoding_t e;
1010 size_t n;
1011
1012 if (*mbc->mbc_offp < off)
1013 return (0);
1014
1015 if (mdb_ctf_type_encoding(id, &e) == -1)
1016 size = mdb_ctf_type_size(id) * NBBY;
1017 else
1018 size = e.cte_bits;
1019
1020 if (off + size <= *mbc->mbc_offp)
1021 return (0);
1022
1023 if (*name == '\0' && (mdb_ctf_type_kind(id) == CTF_K_STRUCT ||
1024 mdb_ctf_type_kind(id) == CTF_K_UNION)) {
1025 n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "<anon>");
1026 } else {
1027 n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "%s", name);
1028 }
1029 mbc->mbc_total += n;
1030 if (n > *mbc->mbc_lenp)
1031 n = *mbc->mbc_lenp;
1032
1033 *mbc->mbc_lenp -= n;
1034 *mbc->mbc_bufp += n;
1035
1036 *mbc->mbc_offp -= off;
1037 *mbc->mbc_idp = id;
1038
1039 return (1);
1040 }
1041
1042 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)1043 mdb_ctf_offset_to_name(mdb_ctf_id_t id, ulong_t off, char *buf, size_t len,
1044 int dot, mdb_ctf_id_t *midp, ulong_t *moffp)
1045 {
1046 size_t size;
1047 size_t n;
1048 mbr_contains_t mbc;
1049
1050 if (!mdb_ctf_type_valid(id))
1051 return (set_errno(EINVAL));
1052
1053 /*
1054 * Quick sanity check to make sure the given offset is within
1055 * this scope of this type.
1056 */
1057 if (mdb_ctf_type_size(id) * NBBY <= off)
1058 return (set_errno(EINVAL));
1059
1060 mbc.mbc_bufp = &buf;
1061 mbc.mbc_lenp = &len;
1062 mbc.mbc_offp = &off;
1063 mbc.mbc_idp = &id;
1064 mbc.mbc_total = 0;
1065
1066 *buf = '\0';
1067
1068 for (;;) {
1069 /*
1070 * Check for an exact match.
1071 */
1072 if (off == 0)
1073 break;
1074
1075 (void) mdb_ctf_type_resolve(id, &id);
1076
1077 /*
1078 * Find the member that contains this offset.
1079 */
1080 switch (mdb_ctf_type_kind(id)) {
1081 case CTF_K_ARRAY: {
1082 mdb_ctf_arinfo_t ar;
1083 uint_t index;
1084
1085 (void) mdb_ctf_array_info(id, &ar);
1086 size = mdb_ctf_type_size(ar.mta_contents) * NBBY;
1087 index = off / size;
1088
1089 id = ar.mta_contents;
1090 off %= size;
1091
1092 n = mdb_snprintf(buf, len, "[%u]", index);
1093 mbc.mbc_total += n;
1094 if (n > len)
1095 n = len;
1096
1097 buf += n;
1098 len -= n;
1099 break;
1100 }
1101
1102 case CTF_K_STRUCT: {
1103 int ret;
1104
1105 /*
1106 * Find the member that contains this offset
1107 * and continue.
1108 */
1109
1110 if (dot) {
1111 mbc.mbc_total++;
1112 if (len != 0) {
1113 *buf++ = '.';
1114 *buf = '\0';
1115 len--;
1116 }
1117 }
1118
1119 ret = mdb_ctf_member_iter(id, offset_to_name_cb, &mbc,
1120 0);
1121 if (ret == -1)
1122 return (-1); /* errno is set for us */
1123
1124 /*
1125 * If we did not find a member containing this offset
1126 * (due to holes in the structure), return EINVAL.
1127 */
1128 if (ret == 0)
1129 return (set_errno(EINVAL));
1130
1131 break;
1132 }
1133
1134 case CTF_K_UNION:
1135 /*
1136 * Treat unions like atomic entities since we can't
1137 * do more than guess which member of the union
1138 * might be the intended one.
1139 */
1140 goto done;
1141
1142 case CTF_K_INTEGER:
1143 case CTF_K_FLOAT:
1144 case CTF_K_POINTER:
1145 case CTF_K_ENUM:
1146 goto done;
1147
1148 default:
1149 return (set_errno(EINVAL));
1150 }
1151
1152 dot = 1;
1153 }
1154 done:
1155 if (midp != NULL)
1156 *midp = id;
1157 if (moffp != NULL)
1158 *moffp = off;
1159
1160 return (mbc.mbc_total);
1161 }
1162
1163 static void
mdb_ctf_warn(uint_t flags,const char * format,...)1164 mdb_ctf_warn(uint_t flags, const char *format, ...)
1165 {
1166 va_list alist;
1167
1168 if (flags & MDB_CTF_VREAD_QUIET)
1169 return;
1170
1171 va_start(alist, format);
1172 vwarn(format, alist);
1173 va_end(alist);
1174 }
1175
1176 /*
1177 * Check if two types are structurally the same rather than logically
1178 * the same. That is to say that two types are equal if they have the
1179 * same logical structure rather than having the same ids in CTF-land.
1180 */
1181 static int type_equals(mdb_ctf_id_t, mdb_ctf_id_t);
1182
1183 static int
type_equals_cb(const char * name,mdb_ctf_id_t amem,ulong_t aoff,void * data)1184 type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data)
1185 {
1186 mdb_ctf_id_t b = *(mdb_ctf_id_t *)data;
1187 ulong_t boff;
1188 mdb_ctf_id_t bmem;
1189
1190 /*
1191 * Look up the corresponding member in the other composite type.
1192 */
1193 if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0)
1194 return (1);
1195
1196 /*
1197 * We don't allow members to be shuffled around.
1198 */
1199 if (aoff != boff)
1200 return (1);
1201
1202 return (type_equals(amem, bmem) ? 0 : 1);
1203 }
1204
1205 static int
type_equals(mdb_ctf_id_t a,mdb_ctf_id_t b)1206 type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b)
1207 {
1208 size_t asz, bsz;
1209 int akind, bkind;
1210 mdb_ctf_arinfo_t aar, bar;
1211
1212 /*
1213 * Resolve both types down to their fundamental types, and make
1214 * sure their sizes and kinds match.
1215 */
1216 if (mdb_ctf_type_resolve(a, &a) != 0 ||
1217 mdb_ctf_type_resolve(b, &b) != 0 ||
1218 (asz = mdb_ctf_type_size(a)) == -1UL ||
1219 (bsz = mdb_ctf_type_size(b)) == -1UL ||
1220 (akind = mdb_ctf_type_kind(a)) == -1 ||
1221 (bkind = mdb_ctf_type_kind(b)) == -1 ||
1222 asz != bsz || akind != bkind) {
1223 return (0);
1224 }
1225
1226 switch (akind) {
1227 case CTF_K_INTEGER:
1228 case CTF_K_FLOAT:
1229 case CTF_K_POINTER:
1230 /*
1231 * For pointers we could be a little stricter and require
1232 * both pointers to reference types which look vaguely
1233 * similar (for example, we could insist that the two types
1234 * have the same name). However, all we really care about
1235 * here is that the structure of the two types are the same,
1236 * and, in that regard, one pointer is as good as another.
1237 */
1238 return (1);
1239
1240 case CTF_K_UNION:
1241 case CTF_K_STRUCT:
1242 /*
1243 * The test for the number of members is only strictly
1244 * necessary for unions since we'll find other problems with
1245 * structs. However, the extra check will do no harm.
1246 */
1247 return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) &&
1248 mdb_ctf_member_iter(a, type_equals_cb, &b, 0) == 0);
1249
1250 case CTF_K_ARRAY:
1251 return (mdb_ctf_array_info(a, &aar) == 0 &&
1252 mdb_ctf_array_info(b, &bar) == 0 &&
1253 aar.mta_nelems == bar.mta_nelems &&
1254 type_equals(aar.mta_index, bar.mta_index) &&
1255 type_equals(aar.mta_contents, bar.mta_contents));
1256 }
1257
1258 return (0);
1259 }
1260
1261
1262 typedef struct member {
1263 char *m_modbuf;
1264 char *m_tgtbuf;
1265 const char *m_tgtname;
1266 mdb_ctf_id_t m_tgtid;
1267 uint_t m_flags;
1268 } member_t;
1269
1270 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *,
1271 const char *, uint_t);
1272
1273 static int
member_cb(const char * name,mdb_ctf_id_t modmid,ulong_t modoff,void * data)1274 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
1275 {
1276 member_t *mp = data;
1277 char *modbuf = mp->m_modbuf;
1278 mdb_ctf_id_t tgtmid;
1279 char *tgtbuf = mp->m_tgtbuf;
1280 ulong_t tgtoff;
1281 char tgtname[128];
1282
1283 (void) mdb_snprintf(tgtname, sizeof (tgtname),
1284 "member %s of type %s", name, mp->m_tgtname);
1285
1286 if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
1287 if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT)
1288 return (0);
1289 mdb_ctf_warn(mp->m_flags, "could not find %s\n", tgtname);
1290 return (set_errno(EMDB_CTFNOMEMB));
1291 }
1292
1293 return (vread_helper(modmid, modbuf + modoff / NBBY,
1294 tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags));
1295 }
1296
1297 typedef struct enum_value {
1298 int *ev_modbuf;
1299 const char *ev_name;
1300 } enum_value_t;
1301
1302 static int
enum_cb(const char * name,int value,void * data)1303 enum_cb(const char *name, int value, void *data)
1304 {
1305 enum_value_t *ev = data;
1306
1307 if (strcmp(name, ev->ev_name) == 0) {
1308 *ev->ev_modbuf = value;
1309 return (1);
1310 }
1311 return (0);
1312 }
1313
1314 static int
vread_helper(mdb_ctf_id_t modid,char * modbuf,mdb_ctf_id_t tgtid,char * tgtbuf,const char * tgtname,uint_t flags)1315 vread_helper(mdb_ctf_id_t modid, char *modbuf,
1316 mdb_ctf_id_t tgtid, char *tgtbuf, const char *tgtname, uint_t flags)
1317 {
1318 size_t modsz, tgtsz;
1319 int modkind, tgtkind, mod_members;
1320 member_t mbr;
1321 enum_value_t ev;
1322 int ret;
1323 mdb_ctf_arinfo_t tar, mar;
1324 int i;
1325 char typename[128];
1326 char mdbtypename[128];
1327 ctf_encoding_t tgt_encoding, mod_encoding;
1328 boolean_t signed_int = B_FALSE;
1329
1330 if (mdb_ctf_type_name(tgtid, typename, sizeof (typename)) == NULL) {
1331 (void) mdb_snprintf(typename, sizeof (typename),
1332 "#%ul", mdb_ctf_type_id(tgtid));
1333 }
1334 if (mdb_ctf_type_name(modid,
1335 mdbtypename, sizeof (mdbtypename)) == NULL) {
1336 (void) mdb_snprintf(mdbtypename, sizeof (mdbtypename),
1337 "#%ul", mdb_ctf_type_id(modid));
1338 }
1339
1340 if (tgtname == NULL)
1341 tgtname = "";
1342
1343 /*
1344 * Resolve the types to their canonical form.
1345 */
1346 (void) mdb_ctf_type_resolve(modid, &modid);
1347 (void) mdb_ctf_type_resolve(tgtid, &tgtid);
1348
1349 if ((modkind = mdb_ctf_type_kind(modid)) == -1) {
1350 mdb_ctf_warn(flags,
1351 "couldn't determine type kind of mdb module type %s\n",
1352 mdbtypename);
1353 return (-1); /* errno is set for us */
1354 }
1355 if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) {
1356 mdb_ctf_warn(flags,
1357 "couldn't determine type kind of %s\n", typename);
1358 return (-1); /* errno is set for us */
1359 }
1360
1361 if ((modsz = mdb_ctf_type_size(modid)) == -1UL) {
1362 mdb_ctf_warn(flags, "couldn't determine type size of "
1363 "mdb module type %s\n", mdbtypename);
1364 return (-1); /* errno is set for us */
1365 }
1366 if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) {
1367 mdb_ctf_warn(flags, "couldn't determine size of %s (%s)\n",
1368 typename, tgtname);
1369 return (-1); /* errno is set for us */
1370 }
1371
1372 if (tgtkind == CTF_K_POINTER && modkind == CTF_K_INTEGER &&
1373 strcmp(mdbtypename, "uintptr_t") == 0) {
1374 /* allow them to convert a pointer to a uintptr_t */
1375 ASSERT(modsz == tgtsz);
1376 } else if (tgtkind != modkind) {
1377 mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n",
1378 typename, tgtname);
1379 return (set_errno(EMDB_INCOMPAT));
1380 }
1381
1382 switch (tgtkind) {
1383 case CTF_K_INTEGER:
1384 case CTF_K_FLOAT:
1385 /*
1386 * Must determine if the target and module types have the same
1387 * encoding before we can copy them.
1388 */
1389 if (mdb_ctf_type_encoding(tgtid, &tgt_encoding) != 0) {
1390 mdb_ctf_warn(flags,
1391 "couldn't determine encoding of type %s (%s)\n",
1392 typename, tgtname);
1393 return (-1); /* errno is set for us */
1394 }
1395 if (mdb_ctf_type_encoding(modid, &mod_encoding) != 0) {
1396 mdb_ctf_warn(flags, "couldn't determine encoding of "
1397 "mdb module type %s\n", mdbtypename);
1398 return (-1); /* errno is set for us */
1399 }
1400
1401 if (modkind == CTF_K_INTEGER) {
1402 if ((tgt_encoding.cte_format & CTF_INT_SIGNED) !=
1403 (mod_encoding.cte_format & CTF_INT_SIGNED)) {
1404 mdb_ctf_warn(flags,
1405 "signedness mismatch between type "
1406 "%s (%s) and mdb module type %s\n",
1407 typename, tgtname, mdbtypename);
1408 return (set_errno(EMDB_INCOMPAT));
1409 }
1410 signed_int =
1411 ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 0);
1412 } else if (tgt_encoding.cte_format != mod_encoding.cte_format) {
1413 mdb_ctf_warn(flags,
1414 "encoding mismatch (%#x != %#x) between type "
1415 "%s (%s) and mdb module type %s\n",
1416 tgt_encoding.cte_format, mod_encoding.cte_format,
1417 typename, tgtname, mdbtypename);
1418 return (set_errno(EMDB_INCOMPAT));
1419 }
1420 /* FALLTHROUGH */
1421 case CTF_K_POINTER:
1422 /*
1423 * If the sizes don't match we need to be tricky to make
1424 * sure that the caller gets the correct data.
1425 */
1426 if (modsz < tgtsz) {
1427 mdb_ctf_warn(flags, "size of type %s (%s) is too "
1428 "large for mdb module type %s\n",
1429 typename, tgtname, mdbtypename);
1430 return (set_errno(EMDB_INCOMPAT));
1431 } else if (modsz > tgtsz) {
1432 /* BEGIN CSTYLED */
1433 /*
1434 * Fill modbuf with 1's for sign extension if target
1435 * buf is a signed integer and its value is negative.
1436 *
1437 * S = sign bit (in most-significant byte)
1438 *
1439 * BIG ENDIAN DATA
1440 * +--------+--------+--------+--------+
1441 * |S | | | |
1442 * +--------+--------+--------+--------+
1443 * 0 1 ... sz-1 sz
1444 *
1445 * LITTLE ENDIAN DATA
1446 * +--------+--------+--------+--------+
1447 * | | | |S |
1448 * +--------+--------+--------+--------+
1449 * 0 1 ... sz-1 sz
1450 */
1451 /* END CSTYLED */
1452 #ifdef _BIG_ENDIAN
1453 if (signed_int && (tgtbuf[0] & 0x80) != 0)
1454 #else
1455 if (signed_int && (tgtbuf[tgtsz - 1] & 0x80) != 0)
1456 #endif
1457 (void) memset(modbuf, 0xFF, modsz);
1458 else
1459 bzero(modbuf, modsz);
1460 #ifdef _BIG_ENDIAN
1461 bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz);
1462 #else
1463 bcopy(tgtbuf, modbuf, tgtsz);
1464 #endif
1465 } else {
1466 bcopy(tgtbuf, modbuf, modsz);
1467 }
1468
1469 return (0);
1470
1471 case CTF_K_ENUM:
1472 if (modsz != tgtsz || modsz != sizeof (int)) {
1473 mdb_ctf_warn(flags, "unexpected size of type %s (%s)\n",
1474 typename, tgtname);
1475 return (set_errno(EMDB_INCOMPAT));
1476 }
1477
1478 /*
1479 * Default to the same value as in the target.
1480 */
1481 bcopy(tgtbuf, modbuf, sizeof (int));
1482
1483 /* LINTED */
1484 i = *(int *)tgtbuf;
1485
1486 /* LINTED */
1487 ev.ev_modbuf = (int *)modbuf;
1488 ev.ev_name = mdb_ctf_enum_name(tgtid, i);
1489 if (ev.ev_name == NULL) {
1490 mdb_ctf_warn(flags,
1491 "unexpected value %u of enum type %s (%s)\n",
1492 i, typename, tgtname);
1493 return (set_errno(EMDB_INCOMPAT));
1494 }
1495
1496 ret = mdb_ctf_enum_iter(modid, enum_cb, &ev);
1497 if (ret == 0) {
1498 /* value not found */
1499 mdb_ctf_warn(flags,
1500 "unexpected value %s (%u) of enum type %s (%s)\n",
1501 ev.ev_name, i, typename, tgtname);
1502 return (set_errno(EMDB_INCOMPAT));
1503 } else if (ret == 1) {
1504 /* value found */
1505 return (0);
1506 } else if (ret == -1) {
1507 mdb_ctf_warn(flags, "could not iterate enum %s (%s)\n",
1508 typename, tgtname);
1509 }
1510 return (ret);
1511
1512 case CTF_K_STRUCT:
1513 mbr.m_modbuf = modbuf;
1514 mbr.m_tgtbuf = tgtbuf;
1515 mbr.m_tgtid = tgtid;
1516 mbr.m_flags = flags;
1517 mbr.m_tgtname = typename;
1518
1519 return (mdb_ctf_member_iter(modid, member_cb, &mbr, 0));
1520
1521 case CTF_K_UNION:
1522 mbr.m_modbuf = modbuf;
1523 mbr.m_tgtbuf = tgtbuf;
1524 mbr.m_tgtid = tgtid;
1525 mbr.m_flags = flags;
1526 mbr.m_tgtname = typename;
1527
1528 /*
1529 * Not all target union members need to be present in the
1530 * mdb type. If there is only a single union member in the
1531 * mdb type, its actual type does not need to match with
1532 * its target's type. On the other hand, if more than one
1533 * union members are specified in the mdb type, their types
1534 * must match with the types of their relevant union members
1535 * of the target union.
1536 */
1537 mod_members = mdb_ctf_num_members(modid);
1538 if (mod_members == 1) {
1539 return (mdb_ctf_member_iter(modid, member_cb, &mbr, 0));
1540 } else if (mod_members > 1) {
1541 if (mdb_ctf_member_iter(modid, type_equals_cb,
1542 &tgtid, 0)) {
1543 mdb_ctf_warn(flags,
1544 "inexact match for union %s (%s)\n",
1545 typename, tgtname);
1546 return (set_errno(EMDB_INCOMPAT));
1547 }
1548
1549 /*
1550 * From the check above we know that the members
1551 * which are present in the mdb type are equal to
1552 * the types in the target. Thus, the member_cb
1553 * callback below will not move anything around and
1554 * it is equivalent to:
1555 *
1556 * bcopy(tgtbuf, modbuf, MAX(module member's sizes))
1557 */
1558 return (mdb_ctf_member_iter(modid, member_cb, &mbr, 0));
1559 } else {
1560 /*
1561 * We either got 0 or -1. In any case that number
1562 * should be returned right away. For the error
1563 * case of -1, errno has been set for us.
1564 */
1565 return (mod_members);
1566 }
1567
1568 case CTF_K_ARRAY:
1569 if (mdb_ctf_array_info(tgtid, &tar) != 0) {
1570 mdb_ctf_warn(flags,
1571 "couldn't get array info for %s (%s)\n",
1572 typename, tgtname);
1573 return (-1); /* errno is set for us */
1574 }
1575 if (mdb_ctf_array_info(modid, &mar) != 0) {
1576 mdb_ctf_warn(flags,
1577 "couldn't get array info for mdb module type %s\n",
1578 mdbtypename);
1579 return (-1); /* errno is set for us */
1580 }
1581
1582 if (tar.mta_nelems != mar.mta_nelems) {
1583 mdb_ctf_warn(flags,
1584 "unexpected array size (%u) for type %s (%s)\n",
1585 tar.mta_nelems, typename, tgtname);
1586 return (set_errno(EMDB_INCOMPAT));
1587 }
1588
1589 if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) {
1590 mdb_ctf_warn(flags, "couldn't determine type size of "
1591 "mdb module type %s\n", mdbtypename);
1592 return (-1); /* errno is set for us */
1593 }
1594 if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) {
1595 mdb_ctf_warn(flags,
1596 "couldn't determine size of %s (%s)\n",
1597 typename, tgtname);
1598 return (-1); /* errno is set for us */
1599 }
1600
1601 for (i = 0; i < tar.mta_nelems; i++) {
1602 ret = vread_helper(mar.mta_contents, modbuf + i * modsz,
1603 tar.mta_contents, tgtbuf + i * tgtsz,
1604 tgtname, flags);
1605
1606 if (ret != 0)
1607 return (ret);
1608 }
1609
1610 return (0);
1611 }
1612
1613 mdb_ctf_warn(flags, "unsupported kind %d for type %s (%s)\n",
1614 modkind, typename, tgtname);
1615 return (set_errno(EMDB_INCOMPAT));
1616 }
1617
1618 /*
1619 * Like mdb_vread(), mdb_ctf_vread() is used to read from the target's
1620 * virtual address space. However, mdb_ctf_vread() can be used to safely
1621 * read a complex type (e.g. a struct) from the target, even if MDB was compiled
1622 * against a different definition of that type (e.g. when debugging a crash
1623 * dump from an older release).
1624 *
1625 * Callers can achieve this by defining their own type which corresponds to the
1626 * type in the target, but contains only the members that the caller requires.
1627 * Using the CTF type information embedded in the target, mdb_ctf_vread will
1628 * find the required members in the target and fill in the caller's structure.
1629 * The members are located by name, and their types are verified to be
1630 * compatible.
1631 *
1632 * By convention, the caller will declare a type with the name "mdb_<type>",
1633 * where <type> is the name of the type in the target (e.g. mdb_zio_t). This
1634 * type will contain the members that the caller is interested in. For example:
1635 *
1636 * typedef struct mdb_zio {
1637 * enum zio_type io_type;
1638 * uintptr_t io_waiter;
1639 * struct {
1640 * struct {
1641 * uintptr_t list_next;
1642 * } list_head;
1643 * } io_parent_list;
1644 * int io_error;
1645 * } mdb_zio_t;
1646 *
1647 * mdb_zio_t zio;
1648 * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0);
1649 *
1650 * If a given MDB module has different dcmds or walkers that need to read
1651 * different members from the same struct, then different "mdb_" types
1652 * should be declared for each caller. By convention, these types should
1653 * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t
1654 * for ::findstack. If the MDB module is compiled from several source files,
1655 * one must be especially careful to not define different types with the
1656 * same name in different source files, because the compiler can not detect
1657 * this error.
1658 *
1659 * Enums will also be translated by name, so the mdb module will receive
1660 * the enum value it expects even if the target has renumbered the enum.
1661 * Warning: it will therefore only work with enums are only used to store
1662 * legitimate enum values (not several values or-ed together).
1663 *
1664 * Flags values:
1665 *
1666 * MDB_CTF_VREAD_QUIET: keep quiet about failures
1667 * MDB_CTF_VREAD_IGNORE_ABSENT: ignore any member that couldn't be found in the
1668 * target struct; be careful not to use an uninitialized result.
1669 */
1670 int
mdb_ctf_vread(void * modbuf,const char * target_typename,const char * mdb_typename,uintptr_t addr,uint_t flags)1671 mdb_ctf_vread(void *modbuf, const char *target_typename,
1672 const char *mdb_typename, uintptr_t addr, uint_t flags)
1673 {
1674 ctf_file_t *mfp;
1675 ctf_id_t mid;
1676 void *tgtbuf;
1677 size_t size;
1678 mdb_ctf_id_t tgtid;
1679 mdb_ctf_id_t modid;
1680 mdb_module_t *mod;
1681 int ret;
1682
1683 if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
1684 mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
1685 mod->mod_name);
1686 return (set_errno(EMDB_NOCTF));
1687 }
1688
1689 if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) {
1690 mdb_ctf_warn(flags, "couldn't find ctf data for "
1691 "type %s in mdb module %s\n",
1692 mdb_typename, mod->mod_name);
1693 return (set_errno(ctf_to_errno(ctf_errno(mfp))));
1694 }
1695
1696 set_ctf_id(&modid, mfp, mid);
1697
1698 if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) {
1699 mdb_ctf_warn(flags,
1700 "couldn't find type %s in target's ctf data\n",
1701 target_typename);
1702 return (set_errno(EMDB_NOCTF));
1703 }
1704
1705 /*
1706 * Read the data out of the target's address space.
1707 */
1708 if ((size = mdb_ctf_type_size(tgtid)) == -1UL) {
1709 mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
1710 target_typename);
1711 return (-1); /* errno is set for us */
1712 }
1713
1714 tgtbuf = mdb_alloc(size, UM_SLEEP);
1715
1716 if (mdb_vread(tgtbuf, size, addr) < 0) {
1717 mdb_ctf_warn(flags, "couldn't read %s from %p\n",
1718 target_typename, addr);
1719 mdb_free(tgtbuf, size);
1720 return (-1); /* errno is set for us */
1721 }
1722
1723 ret = vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags);
1724
1725 mdb_free(tgtbuf, size);
1726
1727 return (ret);
1728 }
1729
1730 /*
1731 * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
1732 * of the target's type vs the mdb module's type. Use with complicated
1733 * types (e.g. structs) may result in unnecessary failure if a member of
1734 * the struct has been changed in the target, but is not actually needed
1735 * by the mdb module. Use mdb_lookup_by_name() + mdb_ctf_vread() to
1736 * avoid this problem.
1737 */
1738 int
mdb_ctf_readsym(void * buf,const char * typename,const char * name,uint_t flags)1739 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
1740 {
1741 GElf_Sym sym;
1742
1743 if (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, name, &sym) != 0) {
1744 mdb_ctf_warn(flags, "couldn't find symbol %s\n", name);
1745 return (-1); /* errno is set for us */
1746 }
1747
1748 return (mdb_ctf_vread(buf, typename, typename, sym.st_value, flags));
1749 }
1750
1751 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)1752 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va,
1753 Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp)
1754 {
1755 ctf_sect_t ctdata, symtab, strtab;
1756
1757 ctdata.cts_name = ".SUNW_ctf";
1758 ctdata.cts_type = SHT_PROGBITS;
1759 ctdata.cts_flags = 0;
1760 ctdata.cts_data = ctf_va;
1761 ctdata.cts_size = ctf_size;
1762 ctdata.cts_entsize = 1;
1763 ctdata.cts_offset = 0;
1764
1765 symtab.cts_name = ".symtab";
1766 symtab.cts_type = symhdr->sh_type;
1767 symtab.cts_flags = symhdr->sh_flags;
1768 symtab.cts_data = sym_va;
1769 symtab.cts_size = symhdr->sh_size;
1770 symtab.cts_entsize = symhdr->sh_entsize;
1771 symtab.cts_offset = symhdr->sh_offset;
1772
1773 strtab.cts_name = ".strtab";
1774 strtab.cts_type = strhdr->sh_type;
1775 strtab.cts_flags = strhdr->sh_flags;
1776 strtab.cts_data = str_va;
1777 strtab.cts_size = strhdr->sh_size;
1778 strtab.cts_entsize = strhdr->sh_entsize;
1779 strtab.cts_offset = strhdr->sh_offset;
1780
1781 return (ctf_bufopen(&ctdata, &symtab, &strtab, errp));
1782 }
1783
1784 int
mdb_ctf_synthetics_init(void)1785 mdb_ctf_synthetics_init(void)
1786 {
1787 int err;
1788
1789 if ((mdb.m_synth = ctf_create(&err)) == NULL)
1790 return (set_errno(ctf_to_errno(err)));
1791
1792 return (0);
1793 }
1794
1795 void
mdb_ctf_synthetics_fini(void)1796 mdb_ctf_synthetics_fini(void)
1797 {
1798 if (mdb.m_synth == NULL)
1799 return;
1800
1801 ctf_close(mdb.m_synth);
1802 mdb.m_synth = NULL;
1803 }
1804
1805 int
mdb_ctf_synthetics_create_base(int kind)1806 mdb_ctf_synthetics_create_base(int kind)
1807 {
1808 const synth_intrinsic_t *synp;
1809 const synth_typedef_t *sytp;
1810 int err;
1811 ctf_id_t id;
1812 ctf_file_t *cp = mdb.m_synth;
1813
1814 if (mdb.m_synth == NULL) {
1815 mdb_printf("synthetic types disabled: ctf create failed\n");
1816 return (1);
1817 }
1818
1819 switch (kind) {
1820 case SYNTHETIC_ILP32:
1821 synp = synth_builtins32;
1822 sytp = synth_typedefs32;
1823 break;
1824 case SYNTHETIC_LP64:
1825 synp = synth_builtins64;
1826 sytp = synth_typedefs64;
1827 break;
1828 default:
1829 mdb_dprintf(MDB_DBG_CTF, "invalid type of intrinsic: %d\n",
1830 kind);
1831 return (1);
1832 }
1833
1834 err = 0;
1835 for (; synp->syn_name != NULL; synp++) {
1836 if (synp->syn_kind == CTF_K_INTEGER) {
1837 err = ctf_add_integer(cp, CTF_ADD_ROOT, synp->syn_name,
1838 &synp->syn_enc);
1839 } else {
1840 err = ctf_add_float(cp, CTF_ADD_ROOT, synp->syn_name,
1841 &synp->syn_enc);
1842 }
1843
1844 if (err == CTF_ERR) {
1845 mdb_dprintf(MDB_DBG_CTF, "couldn't add synthetic "
1846 "type: %s\n", synp->syn_name);
1847 goto discard;
1848 }
1849 }
1850
1851 if (ctf_update(cp) == CTF_ERR) {
1852 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
1853 goto discard;
1854 }
1855
1856 for (; sytp->syt_src != NULL; sytp++) {
1857 id = ctf_lookup_by_name(cp, sytp->syt_src);
1858 if (id == CTF_ERR) {
1859 mdb_dprintf(MDB_DBG_CTF, "cailed to lookup %s: %s\n",
1860 sytp->syt_src, ctf_errmsg(ctf_errno(cp)));
1861 goto discard;
1862 }
1863 if (ctf_add_typedef(cp, CTF_ADD_ROOT, sytp->syt_targ, id) ==
1864 CTF_ERR) {
1865 mdb_dprintf(MDB_DBG_CTF, "couldn't add typedef %s "
1866 "%s: %s\n", sytp->syt_targ, sytp->syt_src,
1867 ctf_errmsg(ctf_errno(cp)));
1868 goto discard;
1869 }
1870 }
1871
1872 if (ctf_update(cp) == CTF_ERR) {
1873 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
1874 goto discard;
1875 }
1876
1877 return (0);
1878
1879 discard:
1880 err = set_errno(ctf_to_errno(ctf_errno(cp)));
1881 (void) ctf_discard(cp);
1882 return (err);
1883 }
1884
1885 int
mdb_ctf_synthetics_reset(void)1886 mdb_ctf_synthetics_reset(void)
1887 {
1888 mdb_ctf_synthetics_fini();
1889 return (mdb_ctf_synthetics_init());
1890 }
1891
1892 int
mdb_ctf_add_typedef(const char * name,const mdb_ctf_id_t * p,mdb_ctf_id_t * new)1893 mdb_ctf_add_typedef(const char *name, const mdb_ctf_id_t *p, mdb_ctf_id_t *new)
1894 {
1895 ctf_id_t rid;
1896 mdb_ctf_id_t tid;
1897 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
1898
1899 if (mdb.m_synth == NULL) {
1900 mdb_printf("synthetic types disabled: ctf create failed\n");
1901 return (1);
1902 }
1903
1904 if (mdb_ctf_lookup_by_name(name, &tid) == 0) {
1905 mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1906 "with that name already exists\n", name);
1907 return (set_errno(EEXIST));
1908 }
1909
1910 rid = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
1911 if (rid == CTF_ERR) {
1912 mdb_dprintf(MDB_DBG_CTF, "failed to add reference type: %s\n",
1913 ctf_errmsg(ctf_errno(mdb.m_synth)));
1914 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1915 }
1916 rid = ctf_add_typedef(mdb.m_synth, CTF_ADD_ROOT, name, rid);
1917 if (rid == CTF_ERR) {
1918 mdb_dprintf(MDB_DBG_CTF, "failed to add typedef: %s",
1919 ctf_errmsg(ctf_errno(mdb.m_synth)));
1920 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1921 }
1922
1923 if (ctf_update(mdb.m_synth) == CTF_ERR) {
1924 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1925 ctf_errmsg(ctf_errno(mdb.m_synth)));
1926 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1927 }
1928
1929 if (new != NULL)
1930 set_ctf_id(new, mdb.m_synth, rid);
1931
1932 return (0);
1933 }
1934
1935 int
mdb_ctf_add_struct(const char * name,mdb_ctf_id_t * rid)1936 mdb_ctf_add_struct(const char *name, mdb_ctf_id_t *rid)
1937 {
1938 mdb_ctf_id_t tid;
1939 ctf_id_t id;
1940
1941 if (mdb.m_synth == NULL) {
1942 mdb_printf("synthetic types disabled: ctf create failed\n");
1943 return (1);
1944 }
1945
1946 if (name != NULL && mdb_ctf_lookup_by_name(name, &tid) == 0) {
1947 mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1948 "with that name already exists\n", name);
1949 return (set_errno(EEXIST));
1950 }
1951
1952 if ((id = ctf_add_struct(mdb.m_synth, CTF_ADD_ROOT, name)) ==
1953 CTF_ERR) {
1954 mdb_dprintf(MDB_DBG_CTF, "failed to add struct: %s\n",
1955 ctf_errmsg(ctf_errno(mdb.m_synth)));
1956 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1957 }
1958
1959 if (ctf_update(mdb.m_synth) == CTF_ERR) {
1960 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1961 ctf_errmsg(ctf_errno(mdb.m_synth)));
1962 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1963 }
1964
1965 if (rid != NULL)
1966 set_ctf_id(rid, mdb.m_synth, id);
1967
1968 return (0);
1969 }
1970
1971 int
mdb_ctf_add_union(const char * name,mdb_ctf_id_t * rid)1972 mdb_ctf_add_union(const char *name, mdb_ctf_id_t *rid)
1973 {
1974 mdb_ctf_id_t tid;
1975 ctf_id_t id;
1976
1977 if (mdb.m_synth == NULL) {
1978 mdb_printf("synthetic types disabled: ctf create failed\n");
1979 return (1);
1980 }
1981
1982 if (name != NULL && mdb_ctf_lookup_by_name(name, &tid) == 0) {
1983 mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1984 "with that name already exists\n", name);
1985 return (set_errno(EEXIST));
1986 }
1987
1988 if ((id = ctf_add_union(mdb.m_synth, CTF_ADD_ROOT, name)) ==
1989 CTF_ERR) {
1990 mdb_dprintf(MDB_DBG_CTF, "failed to add union: %s\n",
1991 ctf_errmsg(ctf_errno(mdb.m_synth)));
1992 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1993 }
1994
1995 if (ctf_update(mdb.m_synth) == CTF_ERR) {
1996 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1997 ctf_errmsg(ctf_errno(mdb.m_synth)));
1998 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1999 }
2000
2001 if (rid != NULL)
2002 set_ctf_id(rid, mdb.m_synth, id);
2003
2004 return (0);
2005 }
2006
2007 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)2008 mdb_ctf_add_member(const mdb_ctf_id_t *p, const char *name,
2009 const mdb_ctf_id_t *mtype, mdb_ctf_id_t *rid)
2010 {
2011 ctf_id_t id, mtid;
2012 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
2013 mdb_ctf_impl_t *mcim = (mdb_ctf_impl_t *)mtype;
2014
2015 if (mdb.m_synth == NULL) {
2016 mdb_printf("synthetic types disabled: ctf create failed\n");
2017 return (DCMD_ERR);
2018 }
2019
2020 if (mcip->mci_fp != mdb.m_synth) {
2021 mdb_dprintf(MDB_DBG_CTF, "requested to add member to a type "
2022 "that wasn't created from a synthetic\n");
2023 return (set_errno(EINVAL));
2024 }
2025
2026 mtid = ctf_add_type(mdb.m_synth, mcim->mci_fp, mcim->mci_id);
2027 if (mtid == CTF_ERR) {
2028 mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
2029 ctf_errmsg(ctf_errno(mdb.m_synth)));
2030 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2031 }
2032
2033 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2034 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2035 ctf_errmsg(ctf_errno(mdb.m_synth)));
2036 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2037 }
2038
2039 id = ctf_add_member(mdb.m_synth, mcip->mci_id, name, mtid, ULONG_MAX);
2040 if (id == CTF_ERR) {
2041 mdb_dprintf(MDB_DBG_CTF, "failed to add member %s: %s\n",
2042 name, ctf_errmsg(ctf_errno(mdb.m_synth)));
2043 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2044 }
2045
2046 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2047 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2048 ctf_errmsg(ctf_errno(mdb.m_synth)));
2049 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2050 }
2051
2052 if (rid != NULL)
2053 set_ctf_id(rid, mdb.m_synth, id);
2054
2055 return (0);
2056 }
2057
2058 int
mdb_ctf_add_array(const mdb_ctf_arinfo_t * marp,mdb_ctf_id_t * rid)2059 mdb_ctf_add_array(const mdb_ctf_arinfo_t *marp, mdb_ctf_id_t *rid)
2060 {
2061 mdb_ctf_impl_t *mcip;
2062 ctf_arinfo_t car;
2063 ctf_id_t id;
2064
2065 if (mdb.m_synth == NULL) {
2066 mdb_printf("synthetic types disabled: ctf create failed\n");
2067 return (1);
2068 }
2069
2070 car.ctr_nelems = marp->mta_nelems;
2071
2072 mcip = (mdb_ctf_impl_t *)&marp->mta_contents;
2073 id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2074 if (id == CTF_ERR) {
2075 mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
2076 ctf_errmsg(ctf_errno(mdb.m_synth)));
2077 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2078 }
2079 car.ctr_contents = id;
2080
2081 mcip = (mdb_ctf_impl_t *)&marp->mta_index;
2082 id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2083 if (id == CTF_ERR) {
2084 mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
2085 ctf_errmsg(ctf_errno(mdb.m_synth)));
2086 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2087 }
2088 car.ctr_index = id;
2089
2090 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2091 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2092 ctf_errmsg(ctf_errno(mdb.m_synth)));
2093 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2094 }
2095
2096 id = ctf_add_array(mdb.m_synth, CTF_ADD_ROOT, &car);
2097 if (id == CTF_ERR) {
2098 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2099 ctf_errmsg(ctf_errno(mdb.m_synth)));
2100 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2101 }
2102
2103 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2104 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2105 ctf_errmsg(ctf_errno(mdb.m_synth)));
2106 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2107 }
2108
2109 if (rid != NULL)
2110 set_ctf_id(rid, mdb.m_synth, id);
2111
2112 return (0);
2113 }
2114
2115 int
mdb_ctf_add_pointer(const mdb_ctf_id_t * p,mdb_ctf_id_t * rid)2116 mdb_ctf_add_pointer(const mdb_ctf_id_t *p, mdb_ctf_id_t *rid)
2117 {
2118 ctf_id_t id;
2119 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
2120
2121 if (mdb.m_synth == NULL) {
2122 mdb_printf("synthetic types disabled: ctf create failed\n");
2123 return (1);
2124 }
2125
2126 id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2127 if (id == CTF_ERR) {
2128 mdb_dprintf(MDB_DBG_CTF, "failed to add pointer type: %s\n",
2129 ctf_errmsg(ctf_errno(mdb.m_synth)));
2130 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2131 }
2132
2133 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2134 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2135 ctf_errmsg(ctf_errno(mdb.m_synth)));
2136 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2137 }
2138
2139
2140 id = ctf_add_pointer(mdb.m_synth, CTF_ADD_ROOT, NULL, id);
2141 if (id == CTF_ERR) {
2142 mdb_dprintf(MDB_DBG_CTF, "failed to add pointer: %s\n",
2143 ctf_errmsg(ctf_errno(mdb.m_synth)));
2144 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2145 }
2146
2147 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2148 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2149 ctf_errmsg(ctf_errno(mdb.m_synth)));
2150 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2151 }
2152
2153
2154 if (rid != NULL)
2155 set_ctf_id(rid, mdb.m_synth, id);
2156
2157 return (0);
2158 }
2159
2160 int
mdb_ctf_type_delete(const mdb_ctf_id_t * id)2161 mdb_ctf_type_delete(const mdb_ctf_id_t *id)
2162 {
2163 int ret;
2164
2165 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)id;
2166
2167 if (mcip->mci_fp != mdb.m_synth) {
2168 mdb_warn("bad ctf_file_t, expected synth container\n");
2169 return (1);
2170 }
2171
2172 ret = ctf_delete_type(mcip->mci_fp, mcip->mci_id);
2173 if (ret != 0) {
2174 mdb_dprintf(MDB_DBG_CTF, "failed to delete synthetic type: %s",
2175 ctf_errmsg(ctf_errno(mdb.m_synth)));
2176 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2177 }
2178
2179 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2180 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2181 ctf_errmsg(ctf_errno(mdb.m_synth)));
2182 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2183 }
2184
2185 return (0);
2186 }
2187
2188 /* ARGSUSED */
2189 static int
mdb_ctf_synthetics_file_cb(mdb_ctf_id_t id,void * arg)2190 mdb_ctf_synthetics_file_cb(mdb_ctf_id_t id, void *arg)
2191 {
2192 ctf_file_t *targ = arg;
2193 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)&id;
2194
2195 if (ctf_add_type(targ, mcip->mci_fp, mcip->mci_id) == CTF_ERR) {
2196 mdb_dprintf(MDB_DBG_CTF, "failed to add type %d: %s\n",
2197 mcip->mci_id, ctf_errmsg(ctf_errno(mcip->mci_fp)));
2198 return (set_errno(ctf_to_errno(ctf_errno(mcip->mci_fp))));
2199 }
2200
2201 return (0);
2202 }
2203
2204 int
mdb_ctf_synthetics_from_file(const char * file)2205 mdb_ctf_synthetics_from_file(const char *file)
2206 {
2207 ctf_file_t *fp, *syn = mdb.m_synth;
2208 int ret;
2209 type_iter_t ti;
2210
2211 if (syn == NULL) {
2212 mdb_warn("synthetic types disabled: ctf create failed\n");
2213 return (1);
2214 }
2215
2216 if ((fp = mdb_ctf_open(file, &ret)) == NULL) {
2217 mdb_warn("failed to parse ctf data in %s: %s\n", file,
2218 ctf_errmsg(ret));
2219 return (1);
2220 }
2221
2222 ret = DCMD_OK;
2223 ti.ti_fp = fp;
2224 ti.ti_arg = syn;
2225 ti.ti_cb = mdb_ctf_synthetics_file_cb;
2226 if (ctf_type_iter(fp, B_FALSE, type_iter_cb, &ti) == CTF_ERR) {
2227 ret = set_errno(ctf_to_errno(ctf_errno(fp)));
2228 mdb_warn("failed to add types");
2229 goto cleanup;
2230 }
2231
2232 if (ctf_update(syn) == CTF_ERR) {
2233 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
2234 ret = set_errno(ctf_to_errno(ctf_errno(fp)));
2235 }
2236
2237 cleanup:
2238 ctf_close(fp);
2239 if (ret != 0)
2240 (void) ctf_discard(syn);
2241 return (ret);
2242 }
2243
2244 int
mdb_ctf_synthetics_to_file(const char * file)2245 mdb_ctf_synthetics_to_file(const char *file)
2246 {
2247 int err;
2248 ctf_file_t *fp = mdb.m_synth;
2249
2250 if (fp == NULL) {
2251 mdb_warn("synthetic types are disabled, not writing "
2252 "anything\n");
2253 return (DCMD_ERR);
2254 }
2255
2256 err = mdb_ctf_write(file, fp);
2257 if (err != 0) {
2258 if (err == CTF_ERR)
2259 (void) set_errno(ctf_to_errno(ctf_errno(fp)));
2260 else
2261 (void) set_errno(err);
2262 err = DCMD_ERR;
2263 } else {
2264 err = DCMD_OK;
2265 }
2266
2267 return (err);
2268 }
2269
2270 static int
cmd_typelist_type(mdb_ctf_id_t id,void * arg)2271 cmd_typelist_type(mdb_ctf_id_t id, void *arg)
2272 {
2273 char buf[1024];
2274
2275 if (mdb_ctf_type_name(id, buf, sizeof (buf)) != NULL) {
2276 mdb_printf("%s\n", buf);
2277 }
2278 return (0);
2279 }
2280
2281 static int
cmd_typelist_module(void * data,const mdb_map_t * mp,const char * name)2282 cmd_typelist_module(void *data, const mdb_map_t *mp, const char *name)
2283 {
2284 (void) mdb_ctf_type_iter(name, cmd_typelist_type, data);
2285 return (0);
2286 }
2287
2288 int
cmd_typelist(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)2289 cmd_typelist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2290 {
2291 if ((flags & DCMD_ADDRSPEC) != 0) {
2292 return (DCMD_USAGE);
2293 }
2294
2295 (void) mdb_tgt_object_iter(mdb.m_target, cmd_typelist_module, NULL);
2296 (void) mdb_ctf_type_iter(MDB_CTF_SYNTHETIC_ITER, cmd_typelist_type,
2297 NULL);
2298
2299 return (DCMD_OK);
2300 }
2301