8158 Want named threads API
[unleashed.git] / usr / src / cmd / mdb / common / mdb / mdb_ctf.c
blobdde087206c1c8fb796e93dfa8c527683f1bb3a53
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
27 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
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>
38 #include <libctf.h>
39 #include <string.h>
41 typedef struct tnarg {
42 mdb_tgt_t *tn_tgt; /* target to use for lookup */
43 const char *tn_name; /* query string to lookup */
44 ctf_file_t *tn_fp; /* CTF container from match */
45 ctf_id_t tn_id; /* CTF type ID from match */
46 } tnarg_t;
48 typedef struct type_iter {
49 mdb_ctf_type_f *ti_cb;
50 void *ti_arg;
51 ctf_file_t *ti_fp;
52 } type_iter_t;
54 typedef struct member_iter {
55 mdb_ctf_member_f *mi_cb;
56 void *mi_arg;
57 ctf_file_t *mi_fp;
58 } member_iter_t;
60 typedef struct type_visit {
61 mdb_ctf_visit_f *tv_cb;
62 void *tv_arg;
63 ctf_file_t *tv_fp;
64 ulong_t tv_base_offset; /* used when recursing from type_cb() */
65 int tv_base_depth; /* used when recursing from type_cb() */
66 int tv_min_depth;
67 } type_visit_t;
69 typedef struct mbr_info {
70 const char *mbr_member;
71 ulong_t *mbr_offp;
72 mdb_ctf_id_t *mbr_typep;
73 } mbr_info_t;
75 typedef struct synth_intrinsic {
76 const char *syn_name;
77 ctf_encoding_t syn_enc;
78 uint_t syn_kind;
79 } synth_intrinsic_t;
81 typedef struct synth_typedef {
82 const char *syt_src;
83 const char *syt_targ;
84 } synth_typedef_t;
87 * As part of our support for synthetic types via ::typedef, we define a core
88 * set of types.
90 static const synth_intrinsic_t synth_builtins32[] = {
91 { "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER },
92 { "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
93 { "unsigned", { 0, 0, 32 }, CTF_K_INTEGER },
94 { "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
95 { "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
96 { "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
97 { "long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
98 { "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
99 { "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
100 { "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
101 { "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
102 { "signed long", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
103 { "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
104 { "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
105 { "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER },
106 { "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER },
107 { "unsigned long", { 0, 0, 32 }, CTF_K_INTEGER },
108 { "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER },
109 { "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER },
110 { "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT },
111 { "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT },
112 { "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT },
113 { "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT },
114 { "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT },
115 { "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT },
116 { "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT },
117 { "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT },
118 { "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT },
119 { NULL, { 0, 0, 0}, 0 }
122 static const synth_intrinsic_t synth_builtins64[] = {
123 { "void", { CTF_INT_SIGNED, 0, 0 }, CTF_K_INTEGER },
124 { "signed", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
125 { "unsigned", { 0, 0, 32 }, CTF_K_INTEGER },
126 { "char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
127 { "short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
128 { "int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
129 { "long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
130 { "long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
131 { "signed char", { CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
132 { "signed short", { CTF_INT_SIGNED, 0, 16 }, CTF_K_INTEGER },
133 { "signed int", { CTF_INT_SIGNED, 0, 32 }, CTF_K_INTEGER },
134 { "signed long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
135 { "signed long long", { CTF_INT_SIGNED, 0, 64 }, CTF_K_INTEGER },
136 { "unsigned char", { CTF_INT_CHAR, 0, 8 }, CTF_K_INTEGER },
137 { "unsigned short", { 0, 0, 16 }, CTF_K_INTEGER },
138 { "unsigned int", { 0, 0, 32 }, CTF_K_INTEGER },
139 { "unsigned long", { 0, 0, 64 }, CTF_K_INTEGER },
140 { "unsigned long long", { 0, 0, 64 }, CTF_K_INTEGER },
141 { "_Bool", { CTF_INT_BOOL, 0, 8 }, CTF_K_INTEGER },
142 { "float", { CTF_FP_SINGLE, 0, 32 }, CTF_K_FLOAT },
143 { "double", { CTF_FP_DOUBLE, 0, 64 }, CTF_K_FLOAT },
144 { "long double", { CTF_FP_LDOUBLE, 0, 128 }, CTF_K_FLOAT },
145 { "float imaginary", { CTF_FP_IMAGRY, 0, 32 }, CTF_K_FLOAT },
146 { "double imaginary", { CTF_FP_DIMAGRY, 0, 64 }, CTF_K_FLOAT },
147 { "long double imaginary", { CTF_FP_LDIMAGRY, 0, 128 }, CTF_K_FLOAT },
148 { "float complex", { CTF_FP_CPLX, 0, 64 }, CTF_K_FLOAT },
149 { "double complex", { CTF_FP_DCPLX, 0, 128 }, CTF_K_FLOAT },
150 { "long double complex", { CTF_FP_LDCPLX, 0, 256 }, CTF_K_FLOAT },
151 { NULL, { 0, 0, 0 }, 0 }
154 static const synth_typedef_t synth_typedefs32[] = {
155 { "char", "int8_t" },
156 { "short", "int16_t" },
157 { "int", "int32_t" },
158 { "long long", "int64_t" },
159 { "int", "intptr_t" },
160 { "unsigned char", "uint8_t" },
161 { "unsigned short", "uint16_t" },
162 { "unsigned", "uint32_t" },
163 { "unsigned long long", "uint64_t" },
164 { "unsigned char", "uchar_t" },
165 { "unsigned short", "ushort_t" },
166 { "unsigned", "uint_t" },
167 { "unsigned long", "ulong_t" },
168 { "unsigned long long", "u_longlong_t" },
169 { "int", "ptrdiff_t" },
170 { "unsigned", "uintptr_t" },
171 { NULL, NULL }
174 static const synth_typedef_t synth_typedefs64[] = {
175 { "char", "int8_t" },
176 { "short", "int16_t" },
177 { "int", "int32_t" },
178 { "long", "int64_t" },
179 { "long", "intptr_t" },
180 { "unsigned char", "uint8_t" },
181 { "unsigned short", "uint16_t" },
182 { "unsigned", "uint32_t" },
183 { "unsigned long", "uint64_t" },
184 { "unsigned char", "uchar_t" },
185 { "unsigned short", "ushort_t" },
186 { "unsigned", "uint_t" },
187 { "unsigned long", "ulong_t" },
188 { "unsigned long long", "u_longlong_t" },
189 { "long", "ptrdiff_t" },
190 { "unsigned long", "uintptr_t" },
191 { NULL, NULL }
194 static void
195 set_ctf_id(mdb_ctf_id_t *p, ctf_file_t *fp, ctf_id_t id)
197 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
199 mcip->mci_fp = fp;
200 mcip->mci_id = id;
204 * Callback function for mdb_tgt_object_iter used from name_to_type, below,
205 * to search the CTF namespace of each object file for a particular name.
207 /*ARGSUSED*/
208 static int
209 obj_lookup(void *data, const mdb_map_t *mp, const char *name)
211 tnarg_t *tnp = data;
212 ctf_file_t *fp;
213 ctf_id_t id;
215 if ((fp = mdb_tgt_name_to_ctf(tnp->tn_tgt, name)) != NULL &&
216 (id = ctf_lookup_by_name(fp, tnp->tn_name)) != CTF_ERR) {
217 tnp->tn_fp = fp;
218 tnp->tn_id = id;
221 * We may have found a forward declaration. If we did, we'll
222 * note the ID and file pointer, but we'll keep searching in
223 * an attempt to find the real thing. If we found something
224 * real (i.e. not a forward), we stop the iteration.
226 return (ctf_type_kind(fp, id) == CTF_K_FORWARD ? 0 : -1);
229 return (0);
233 * Convert a string type name with an optional leading object specifier into
234 * the corresponding CTF file container and type ID. If an error occurs, we
235 * print an appropriate message and return NULL.
237 static ctf_file_t *
238 name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp)
240 const char *object = MDB_TGT_OBJ_EXEC;
241 ctf_file_t *fp = NULL;
242 ctf_id_t id;
243 tnarg_t arg;
244 char *p, *s;
245 char buf[MDB_SYM_NAMLEN];
246 char *name = &buf[0];
248 (void) mdb_snprintf(buf, sizeof (buf), "%s", cname);
250 if ((p = strrsplit(name, '`')) != NULL) {
252 * We need to shuffle things around a little to support
253 * type names of the form "struct module`name".
255 if ((s = strsplit(name, ' ')) != NULL) {
256 bcopy(cname + (s - name), name, (p - s) - 1);
257 name[(p - s) - 1] = '\0';
258 bcopy(cname, name + (p - s), s - name);
259 p = name + (p - s);
261 if (*name != '\0')
262 object = name;
263 name = p;
267 * Attempt to look up the name in the primary object file. If this
268 * fails and the name was unscoped, search all remaining object files.
269 * Finally, search the synthetic types.
271 if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL ||
272 (id = ctf_lookup_by_name(fp, name)) == CTF_ERR ||
273 ctf_type_kind(fp, id) == CTF_K_FORWARD) &&
274 object == MDB_TGT_OBJ_EXEC) {
276 arg.tn_tgt = t;
277 arg.tn_name = name;
278 arg.tn_fp = NULL;
279 arg.tn_id = CTF_ERR;
281 (void) mdb_tgt_object_iter(t, obj_lookup, &arg);
283 if (arg.tn_id != CTF_ERR) {
284 fp = arg.tn_fp;
285 id = arg.tn_id;
286 } else if (mdb.m_synth != NULL) {
287 if ((id = ctf_lookup_by_name(mdb.m_synth,
288 name)) != CTF_ERR)
289 fp = mdb.m_synth;
293 if (fp == NULL)
294 return (NULL); /* errno is set for us */
296 if (id == CTF_ERR) {
297 (void) set_errno(ctf_to_errno(ctf_errno(fp)));
298 return (NULL);
301 *idp = id;
302 return (fp);
306 * Check to see if there is ctf data in the given object. This is useful
307 * so that we don't enter some loop where every call to lookup fails.
310 mdb_ctf_enabled_by_object(const char *object)
312 mdb_tgt_t *t = mdb.m_target;
314 return (mdb_tgt_name_to_ctf(t, object) != NULL);
318 mdb_ctf_lookup_by_name(const char *name, mdb_ctf_id_t *p)
320 ctf_file_t *fp = NULL;
321 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
322 mdb_tgt_t *t = mdb.m_target;
324 if (mcip == NULL)
325 return (set_errno(EINVAL));
327 if ((fp = name_to_type(t, name, &mcip->mci_id)) == NULL) {
328 mdb_ctf_type_invalidate(p);
329 return (-1); /* errno is set for us */
332 mcip->mci_fp = fp;
334 return (0);
338 mdb_ctf_lookup_by_symbol(const GElf_Sym *symp, const mdb_syminfo_t *sip,
339 mdb_ctf_id_t *p)
341 ctf_file_t *fp = NULL;
342 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
343 mdb_tgt_t *t = mdb.m_target;
345 if (mcip == NULL)
346 return (set_errno(EINVAL));
348 if (symp == NULL || sip == NULL) {
349 mdb_ctf_type_invalidate(p);
350 return (set_errno(EINVAL));
353 if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL) {
354 mdb_ctf_type_invalidate(p);
355 return (-1); /* errno is set for us */
358 if ((mcip->mci_id = ctf_lookup_by_symbol(fp, sip->sym_id)) == CTF_ERR) {
359 mdb_ctf_type_invalidate(p);
360 return (set_errno(ctf_to_errno(ctf_errno(fp))));
363 mcip->mci_fp = fp;
365 return (0);
369 mdb_ctf_lookup_by_addr(uintptr_t addr, mdb_ctf_id_t *p)
371 GElf_Sym sym;
372 mdb_syminfo_t si;
373 char name[MDB_SYM_NAMLEN];
374 const mdb_map_t *mp;
375 mdb_tgt_t *t = mdb.m_target;
376 const char *obj, *c;
378 if (p == NULL)
379 return (set_errno(EINVAL));
381 if (mdb_tgt_lookup_by_addr(t, addr, MDB_TGT_SYM_EXACT, name,
382 sizeof (name), NULL, NULL) == -1) {
383 mdb_ctf_type_invalidate(p);
384 return (-1); /* errno is set for us */
387 if ((c = strrsplit(name, '`')) != NULL) {
388 obj = name;
389 } else {
390 if ((mp = mdb_tgt_addr_to_map(t, addr)) == NULL) {
391 mdb_ctf_type_invalidate(p);
392 return (-1); /* errno is set for us */
395 obj = mp->map_name;
396 c = name;
399 if (mdb_tgt_lookup_by_name(t, obj, c, &sym, &si) == -1) {
400 mdb_ctf_type_invalidate(p);
401 return (-1); /* errno is set for us */
404 return (mdb_ctf_lookup_by_symbol(&sym, &si, p));
408 mdb_ctf_module_lookup(const char *name, mdb_ctf_id_t *p)
410 ctf_file_t *fp;
411 ctf_id_t id;
412 mdb_module_t *mod;
414 if ((mod = mdb_get_module()) == NULL)
415 return (set_errno(EMDB_CTX));
417 if ((fp = mod->mod_ctfp) == NULL)
418 return (set_errno(EMDB_NOCTF));
420 if ((id = ctf_lookup_by_name(fp, name)) == CTF_ERR)
421 return (set_errno(ctf_to_errno(ctf_errno(fp))));
423 set_ctf_id(p, fp, id);
425 return (0);
428 /*ARGSUSED*/
430 mdb_ctf_func_info(const GElf_Sym *symp, const mdb_syminfo_t *sip,
431 mdb_ctf_funcinfo_t *mfp)
433 ctf_file_t *fp = NULL;
434 ctf_funcinfo_t f;
435 mdb_tgt_t *t = mdb.m_target;
436 char name[MDB_SYM_NAMLEN];
437 const mdb_map_t *mp;
438 mdb_syminfo_t si;
439 int err;
441 if (symp == NULL || mfp == NULL)
442 return (set_errno(EINVAL));
445 * In case the input symbol came from a merged or private symbol table,
446 * re-lookup the address as a symbol, and then perform a fully scoped
447 * lookup of that symbol name to get the mdb_syminfo_t for its CTF.
449 if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL ||
450 (mp = mdb_tgt_addr_to_map(t, symp->st_value)) == NULL ||
451 mdb_tgt_lookup_by_addr(t, symp->st_value, MDB_TGT_SYM_FUZZY,
452 name, sizeof (name), NULL, NULL) != 0)
453 return (-1); /* errno is set for us */
455 if (strchr(name, '`') != NULL)
456 err = mdb_tgt_lookup_by_scope(t, name, NULL, &si);
457 else
458 err = mdb_tgt_lookup_by_name(t, mp->map_name, name, NULL, &si);
460 if (err != 0)
461 return (-1); /* errno is set for us */
463 if (ctf_func_info(fp, si.sym_id, &f) == CTF_ERR)
464 return (set_errno(ctf_to_errno(ctf_errno(fp))));
466 set_ctf_id(&mfp->mtf_return, fp, f.ctc_return);
467 mfp->mtf_argc = f.ctc_argc;
468 mfp->mtf_flags = f.ctc_flags;
469 mfp->mtf_symidx = si.sym_id;
471 return (0);
475 mdb_ctf_func_args(const mdb_ctf_funcinfo_t *funcp, uint_t len,
476 mdb_ctf_id_t *argv)
478 ctf_file_t *fp;
479 ctf_id_t cargv[32];
480 int i;
482 if (len > (sizeof (cargv) / sizeof (cargv[0])))
483 return (set_errno(EINVAL));
485 if (funcp == NULL || argv == NULL)
486 return (set_errno(EINVAL));
488 fp = mdb_ctf_type_file(funcp->mtf_return);
490 if (ctf_func_args(fp, funcp->mtf_symidx, len, cargv) == CTF_ERR)
491 return (set_errno(ctf_to_errno(ctf_errno(fp))));
493 for (i = MIN(len, funcp->mtf_argc) - 1; i >= 0; i--) {
494 set_ctf_id(&argv[i], fp, cargv[i]);
497 return (0);
500 void
501 mdb_ctf_type_invalidate(mdb_ctf_id_t *idp)
503 set_ctf_id(idp, NULL, CTF_ERR);
507 mdb_ctf_type_valid(mdb_ctf_id_t id)
509 return (((mdb_ctf_impl_t *)&id)->mci_id != CTF_ERR);
513 mdb_ctf_type_cmp(mdb_ctf_id_t aid, mdb_ctf_id_t bid)
515 mdb_ctf_impl_t *aidp = (mdb_ctf_impl_t *)&aid;
516 mdb_ctf_impl_t *bidp = (mdb_ctf_impl_t *)&bid;
518 return (ctf_type_cmp(aidp->mci_fp, aidp->mci_id,
519 bidp->mci_fp, bidp->mci_id));
523 mdb_ctf_type_resolve(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
525 ctf_id_t id;
526 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&mid;
528 if ((id = ctf_type_resolve(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
529 if (outp)
530 mdb_ctf_type_invalidate(outp);
531 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
534 if (ctf_type_kind(idp->mci_fp, id) == CTF_K_FORWARD) {
535 char name[MDB_SYM_NAMLEN];
536 mdb_ctf_id_t lookup_id;
538 if (ctf_type_name(idp->mci_fp, id, name, sizeof (name)) !=
539 NULL &&
540 mdb_ctf_lookup_by_name(name, &lookup_id) == 0 &&
541 outp != NULL) {
542 *outp = lookup_id;
543 return (0);
547 if (outp != NULL)
548 set_ctf_id(outp, idp->mci_fp, id);
550 return (0);
553 char *
554 mdb_ctf_type_name(mdb_ctf_id_t id, char *buf, size_t len)
556 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
557 char *ret;
559 if (!mdb_ctf_type_valid(id)) {
560 (void) set_errno(EINVAL);
561 return (NULL);
564 ret = ctf_type_name(idp->mci_fp, idp->mci_id, buf, len);
565 if (ret == NULL)
566 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
568 return (ret);
571 ssize_t
572 mdb_ctf_type_size(mdb_ctf_id_t id)
574 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
575 ssize_t ret;
577 /* resolve the type in case there's a forward declaration */
578 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
579 return (ret);
581 if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR)
582 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
584 return (ret);
588 mdb_ctf_type_kind(mdb_ctf_id_t id)
590 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
591 int ret;
593 if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR)
594 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
596 return (ret);
600 mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp)
602 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&mid;
603 ctf_id_t id;
605 if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) {
606 if (outp)
607 mdb_ctf_type_invalidate(outp);
608 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
611 if (outp != NULL)
612 set_ctf_id(outp, idp->mci_fp, id);
614 return (0);
619 mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep)
621 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
623 if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR)
624 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
626 return (0);
630 * callback proxy for mdb_ctf_type_visit
632 static int
633 type_cb(const char *name, ctf_id_t type, ulong_t off, int depth, void *arg)
635 type_visit_t *tvp = arg;
636 mdb_ctf_id_t id;
637 mdb_ctf_id_t base;
638 mdb_ctf_impl_t *basep = (mdb_ctf_impl_t *)&base;
640 int ret;
642 if (depth < tvp->tv_min_depth)
643 return (0);
645 off += tvp->tv_base_offset;
646 depth += tvp->tv_base_depth;
648 set_ctf_id(&id, tvp->tv_fp, type);
650 (void) mdb_ctf_type_resolve(id, &base);
651 if ((ret = tvp->tv_cb(name, id, base, off, depth, tvp->tv_arg)) != 0)
652 return (ret);
655 * If the type resolves to a type in a different file, we must have
656 * followed a forward declaration. We need to recurse into the
657 * new type.
659 if (basep->mci_fp != tvp->tv_fp && mdb_ctf_type_valid(base)) {
660 type_visit_t tv;
662 tv.tv_cb = tvp->tv_cb;
663 tv.tv_arg = tvp->tv_arg;
664 tv.tv_fp = basep->mci_fp;
666 tv.tv_base_offset = off;
667 tv.tv_base_depth = depth;
668 tv.tv_min_depth = 1; /* depth = 0 has already been done */
670 ret = ctf_type_visit(basep->mci_fp, basep->mci_id,
671 type_cb, &tv);
673 return (ret);
677 mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg)
679 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
680 type_visit_t tv;
681 int ret;
683 tv.tv_cb = func;
684 tv.tv_arg = arg;
685 tv.tv_fp = idp->mci_fp;
686 tv.tv_base_offset = 0;
687 tv.tv_base_depth = 0;
688 tv.tv_min_depth = 0;
690 ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv);
692 if (ret == CTF_ERR)
693 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
695 return (ret);
699 mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp)
701 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
702 ctf_arinfo_t car;
704 if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR)
705 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
707 set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents);
708 set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index);
710 arp->mta_nelems = car.ctr_nelems;
712 return (0);
715 const char *
716 mdb_ctf_enum_name(mdb_ctf_id_t id, int value)
718 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
719 const char *ret;
721 /* resolve the type in case there's a forward declaration */
722 if (mdb_ctf_type_resolve(id, &id) != 0)
723 return (NULL);
725 if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL)
726 (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)));
728 return (ret);
732 * callback proxy for mdb_ctf_member_iter
734 static int
735 member_iter_cb(const char *name, ctf_id_t type, ulong_t off, void *data)
737 member_iter_t *mip = data;
738 mdb_ctf_id_t id;
740 set_ctf_id(&id, mip->mi_fp, type);
742 return (mip->mi_cb(name, id, off, mip->mi_arg));
746 mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data)
748 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
749 member_iter_t mi;
750 int ret;
752 /* resolve the type in case there's a forward declaration */
753 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
754 return (ret);
756 mi.mi_cb = cb;
757 mi.mi_arg = data;
758 mi.mi_fp = idp->mci_fp;
760 ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi);
762 if (ret == CTF_ERR)
763 return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))));
765 return (ret);
769 mdb_ctf_enum_iter(mdb_ctf_id_t id, mdb_ctf_enum_f *cb, void *data)
771 mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id;
772 int ret;
774 /* resolve the type in case there's a forward declaration */
775 if ((ret = mdb_ctf_type_resolve(id, &id)) != 0)
776 return (ret);
778 return (ctf_enum_iter(idp->mci_fp, idp->mci_id, cb, data));
782 * callback proxy for mdb_ctf_type_iter
784 static int
785 type_iter_cb(ctf_id_t type, void *data)
787 type_iter_t *tip = data;
788 mdb_ctf_id_t id;
790 set_ctf_id(&id, tip->ti_fp, type);
792 return (tip->ti_cb(id, tip->ti_arg));
796 mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data)
798 ctf_file_t *fp;
799 mdb_tgt_t *t = mdb.m_target;
800 int ret;
801 type_iter_t ti;
803 if (object == MDB_CTF_SYNTHETIC_ITER)
804 fp = mdb.m_synth;
805 else
806 fp = mdb_tgt_name_to_ctf(t, object);
808 if (fp == NULL)
809 return (-1);
811 ti.ti_cb = cb;
812 ti.ti_arg = data;
813 ti.ti_fp = fp;
815 if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR)
816 return (set_errno(ctf_to_errno(ctf_errno(fp))));
818 return (ret);
821 /* utility functions */
823 ctf_id_t
824 mdb_ctf_type_id(mdb_ctf_id_t id)
826 return (((mdb_ctf_impl_t *)&id)->mci_id);
829 ctf_file_t *
830 mdb_ctf_type_file(mdb_ctf_id_t id)
832 return (((mdb_ctf_impl_t *)&id)->mci_fp);
835 static int
836 member_info_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
838 mbr_info_t *mbrp = data;
840 if (strcmp(name, mbrp->mbr_member) == 0) {
841 if (mbrp->mbr_offp != NULL)
842 *(mbrp->mbr_offp) = off;
843 if (mbrp->mbr_typep != NULL)
844 *(mbrp->mbr_typep) = id;
846 return (1);
849 return (0);
853 mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp,
854 mdb_ctf_id_t *typep)
856 mbr_info_t mbr;
857 int rc;
859 mbr.mbr_member = member;
860 mbr.mbr_offp = offp;
861 mbr.mbr_typep = typep;
863 rc = mdb_ctf_member_iter(id, member_info_cb, &mbr);
865 /* couldn't get member list */
866 if (rc == -1)
867 return (-1); /* errno is set for us */
869 /* not a member */
870 if (rc == 0)
871 return (set_errno(EMDB_CTFNOMEMB));
873 return (0);
877 * Returns offset in _bits_ in *retp.
880 mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp)
882 return (mdb_ctf_member_info(id, member, retp, NULL));
886 * Returns offset in _bytes_, or -1 on failure.
889 mdb_ctf_offsetof_by_name(const char *type, const char *member)
891 mdb_ctf_id_t id;
892 ulong_t off;
894 if (mdb_ctf_lookup_by_name(type, &id) == -1) {
895 mdb_warn("couldn't find type %s", type);
896 return (-1);
899 if (mdb_ctf_offsetof(id, member, &off) == -1) {
900 mdb_warn("couldn't find member %s of type %s", member, type);
901 return (-1);
903 if (off % 8 != 0) {
904 mdb_warn("member %s of type %s is an unsupported bitfield\n",
905 member, type);
906 return (-1);
908 off /= 8;
910 return (off);
913 ssize_t
914 mdb_ctf_sizeof_by_name(const char *type)
916 mdb_ctf_id_t id;
917 ssize_t size;
919 if (mdb_ctf_lookup_by_name(type, &id) == -1) {
920 mdb_warn("couldn't find type %s", type);
921 return (-1);
924 if ((size = mdb_ctf_type_size(id)) == -1) {
925 mdb_warn("couldn't determine type size of %s", type);
926 return (-1);
929 return (size);
932 /*ARGSUSED*/
933 static int
934 num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
936 int *count = data;
937 *count = *count + 1;
938 return (0);
942 mdb_ctf_num_members(mdb_ctf_id_t id)
944 int count = 0;
946 if (mdb_ctf_member_iter(id, num_members_cb, &count) != 0)
947 return (-1); /* errno is set for us */
949 return (count);
952 typedef struct mbr_contains {
953 char **mbc_bufp;
954 size_t *mbc_lenp;
955 ulong_t *mbc_offp;
956 mdb_ctf_id_t *mbc_idp;
957 ssize_t mbc_total;
958 } mbr_contains_t;
960 static int
961 offset_to_name_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
963 mbr_contains_t *mbc = data;
964 ulong_t size;
965 ctf_encoding_t e;
966 size_t n;
968 if (*mbc->mbc_offp < off)
969 return (0);
971 if (mdb_ctf_type_encoding(id, &e) == -1)
972 size = mdb_ctf_type_size(id) * NBBY;
973 else
974 size = e.cte_bits;
976 if (off + size <= *mbc->mbc_offp)
977 return (0);
979 n = mdb_snprintf(*mbc->mbc_bufp, *mbc->mbc_lenp, "%s", name);
980 mbc->mbc_total += n;
981 if (n > *mbc->mbc_lenp)
982 n = *mbc->mbc_lenp;
984 *mbc->mbc_lenp -= n;
985 *mbc->mbc_bufp += n;
987 *mbc->mbc_offp -= off;
988 *mbc->mbc_idp = id;
990 return (1);
993 ssize_t
994 mdb_ctf_offset_to_name(mdb_ctf_id_t id, ulong_t off, char *buf, size_t len,
995 int dot, mdb_ctf_id_t *midp, ulong_t *moffp)
997 size_t size;
998 size_t n;
999 mbr_contains_t mbc;
1001 if (!mdb_ctf_type_valid(id))
1002 return (set_errno(EINVAL));
1005 * Quick sanity check to make sure the given offset is within
1006 * this scope of this type.
1008 if (mdb_ctf_type_size(id) * NBBY <= off)
1009 return (set_errno(EINVAL));
1011 mbc.mbc_bufp = &buf;
1012 mbc.mbc_lenp = &len;
1013 mbc.mbc_offp = &off;
1014 mbc.mbc_idp = &id;
1015 mbc.mbc_total = 0;
1017 *buf = '\0';
1019 for (;;) {
1021 * Check for an exact match.
1023 if (off == 0)
1024 break;
1026 (void) mdb_ctf_type_resolve(id, &id);
1029 * Find the member that contains this offset.
1031 switch (mdb_ctf_type_kind(id)) {
1032 case CTF_K_ARRAY: {
1033 mdb_ctf_arinfo_t ar;
1034 uint_t index;
1036 (void) mdb_ctf_array_info(id, &ar);
1037 size = mdb_ctf_type_size(ar.mta_contents) * NBBY;
1038 index = off / size;
1040 id = ar.mta_contents;
1041 off %= size;
1043 n = mdb_snprintf(buf, len, "[%u]", index);
1044 mbc.mbc_total += n;
1045 if (n > len)
1046 n = len;
1048 buf += n;
1049 len -= n;
1050 break;
1053 case CTF_K_STRUCT: {
1054 int ret;
1057 * Find the member that contains this offset
1058 * and continue.
1061 if (dot) {
1062 mbc.mbc_total++;
1063 if (len != 0) {
1064 *buf++ = '.';
1065 *buf = '\0';
1066 len--;
1070 ret = mdb_ctf_member_iter(id, offset_to_name_cb, &mbc);
1071 if (ret == -1)
1072 return (-1); /* errno is set for us */
1075 * If we did not find a member containing this offset
1076 * (due to holes in the structure), return EINVAL.
1078 if (ret == 0)
1079 return (set_errno(EINVAL));
1081 break;
1084 case CTF_K_UNION:
1086 * Treat unions like atomic entities since we can't
1087 * do more than guess which member of the union
1088 * might be the intended one.
1090 goto done;
1092 case CTF_K_INTEGER:
1093 case CTF_K_FLOAT:
1094 case CTF_K_POINTER:
1095 case CTF_K_ENUM:
1096 goto done;
1098 default:
1099 return (set_errno(EINVAL));
1102 dot = 1;
1104 done:
1105 if (midp != NULL)
1106 *midp = id;
1107 if (moffp != NULL)
1108 *moffp = off;
1110 return (mbc.mbc_total);
1113 static void
1114 mdb_ctf_warn(uint_t flags, const char *format, ...)
1116 va_list alist;
1118 if (flags & MDB_CTF_VREAD_QUIET)
1119 return;
1121 va_start(alist, format);
1122 vwarn(format, alist);
1123 va_end(alist);
1127 * Check if two types are structurally the same rather than logically
1128 * the same. That is to say that two types are equal if they have the
1129 * same logical structure rather than having the same ids in CTF-land.
1131 static int type_equals(mdb_ctf_id_t, mdb_ctf_id_t);
1133 static int
1134 type_equals_cb(const char *name, mdb_ctf_id_t amem, ulong_t aoff, void *data)
1136 mdb_ctf_id_t b = *(mdb_ctf_id_t *)data;
1137 ulong_t boff;
1138 mdb_ctf_id_t bmem;
1141 * Look up the corresponding member in the other composite type.
1143 if (mdb_ctf_member_info(b, name, &boff, &bmem) != 0)
1144 return (1);
1147 * We don't allow members to be shuffled around.
1149 if (aoff != boff)
1150 return (1);
1152 return (type_equals(amem, bmem) ? 0 : 1);
1155 static int
1156 type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b)
1158 size_t asz, bsz;
1159 int akind, bkind;
1160 mdb_ctf_arinfo_t aar, bar;
1163 * Resolve both types down to their fundamental types, and make
1164 * sure their sizes and kinds match.
1166 if (mdb_ctf_type_resolve(a, &a) != 0 ||
1167 mdb_ctf_type_resolve(b, &b) != 0 ||
1168 (asz = mdb_ctf_type_size(a)) == -1UL ||
1169 (bsz = mdb_ctf_type_size(b)) == -1UL ||
1170 (akind = mdb_ctf_type_kind(a)) == -1 ||
1171 (bkind = mdb_ctf_type_kind(b)) == -1 ||
1172 asz != bsz || akind != bkind) {
1173 return (0);
1176 switch (akind) {
1177 case CTF_K_INTEGER:
1178 case CTF_K_FLOAT:
1179 case CTF_K_POINTER:
1181 * For pointers we could be a little stricter and require
1182 * both pointers to reference types which look vaguely
1183 * similar (for example, we could insist that the two types
1184 * have the same name). However, all we really care about
1185 * here is that the structure of the two types are the same,
1186 * and, in that regard, one pointer is as good as another.
1188 return (1);
1190 case CTF_K_UNION:
1191 case CTF_K_STRUCT:
1193 * The test for the number of members is only strictly
1194 * necessary for unions since we'll find other problems with
1195 * structs. However, the extra check will do no harm.
1197 return (mdb_ctf_num_members(a) == mdb_ctf_num_members(b) &&
1198 mdb_ctf_member_iter(a, type_equals_cb, &b) == 0);
1200 case CTF_K_ARRAY:
1201 return (mdb_ctf_array_info(a, &aar) == 0 &&
1202 mdb_ctf_array_info(b, &bar) == 0 &&
1203 aar.mta_nelems == bar.mta_nelems &&
1204 type_equals(aar.mta_index, bar.mta_index) &&
1205 type_equals(aar.mta_contents, bar.mta_contents));
1208 return (0);
1212 typedef struct member {
1213 char *m_modbuf;
1214 char *m_tgtbuf;
1215 const char *m_tgtname;
1216 mdb_ctf_id_t m_tgtid;
1217 uint_t m_flags;
1218 } member_t;
1220 static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *,
1221 const char *, uint_t);
1223 static int
1224 member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
1226 member_t *mp = data;
1227 char *modbuf = mp->m_modbuf;
1228 mdb_ctf_id_t tgtmid;
1229 char *tgtbuf = mp->m_tgtbuf;
1230 ulong_t tgtoff;
1231 char tgtname[128];
1233 (void) mdb_snprintf(tgtname, sizeof (tgtname),
1234 "member %s of type %s", name, mp->m_tgtname);
1236 if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
1237 mdb_ctf_warn(mp->m_flags,
1238 "could not find %s\n", tgtname);
1239 return (set_errno(EMDB_CTFNOMEMB));
1242 return (vread_helper(modmid, modbuf + modoff / NBBY,
1243 tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags));
1246 typedef struct enum_value {
1247 int *ev_modbuf;
1248 const char *ev_name;
1249 } enum_value_t;
1251 static int
1252 enum_cb(const char *name, int value, void *data)
1254 enum_value_t *ev = data;
1256 if (strcmp(name, ev->ev_name) == 0) {
1257 *ev->ev_modbuf = value;
1258 return (1);
1260 return (0);
1263 static int
1264 vread_helper(mdb_ctf_id_t modid, char *modbuf,
1265 mdb_ctf_id_t tgtid, char *tgtbuf, const char *tgtname, uint_t flags)
1267 size_t modsz, tgtsz;
1268 int modkind, tgtkind, mod_members;
1269 member_t mbr;
1270 enum_value_t ev;
1271 int ret;
1272 mdb_ctf_arinfo_t tar, mar;
1273 int i;
1274 char typename[128];
1275 char mdbtypename[128];
1276 ctf_encoding_t tgt_encoding, mod_encoding;
1277 boolean_t signed_int = B_FALSE;
1279 if (mdb_ctf_type_name(tgtid, typename, sizeof (typename)) == NULL) {
1280 (void) mdb_snprintf(typename, sizeof (typename),
1281 "#%ul", mdb_ctf_type_id(tgtid));
1283 if (mdb_ctf_type_name(modid,
1284 mdbtypename, sizeof (mdbtypename)) == NULL) {
1285 (void) mdb_snprintf(mdbtypename, sizeof (mdbtypename),
1286 "#%ul", mdb_ctf_type_id(modid));
1289 if (tgtname == NULL)
1290 tgtname = "";
1293 * Resolve the types to their canonical form.
1295 (void) mdb_ctf_type_resolve(modid, &modid);
1296 (void) mdb_ctf_type_resolve(tgtid, &tgtid);
1298 if ((modkind = mdb_ctf_type_kind(modid)) == -1) {
1299 mdb_ctf_warn(flags,
1300 "couldn't determine type kind of mdb module type %s\n",
1301 mdbtypename);
1302 return (-1); /* errno is set for us */
1304 if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) {
1305 mdb_ctf_warn(flags,
1306 "couldn't determine type kind of %s\n", typename);
1307 return (-1); /* errno is set for us */
1310 if ((modsz = mdb_ctf_type_size(modid)) == -1UL) {
1311 mdb_ctf_warn(flags, "couldn't determine type size of "
1312 "mdb module type %s\n", mdbtypename);
1313 return (-1); /* errno is set for us */
1315 if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) {
1316 mdb_ctf_warn(flags, "couldn't determine size of %s (%s)\n",
1317 typename, tgtname);
1318 return (-1); /* errno is set for us */
1321 if (tgtkind == CTF_K_POINTER && modkind == CTF_K_INTEGER &&
1322 strcmp(mdbtypename, "uintptr_t") == 0) {
1323 /* allow them to convert a pointer to a uintptr_t */
1324 ASSERT(modsz == tgtsz);
1325 } else if (tgtkind != modkind) {
1326 mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n",
1327 typename, tgtname);
1328 return (set_errno(EMDB_INCOMPAT));
1331 switch (tgtkind) {
1332 case CTF_K_INTEGER:
1333 case CTF_K_FLOAT:
1335 * Must determine if the target and module types have the same
1336 * encoding before we can copy them.
1338 if (mdb_ctf_type_encoding(tgtid, &tgt_encoding) != 0) {
1339 mdb_ctf_warn(flags,
1340 "couldn't determine encoding of type %s (%s)\n",
1341 typename, tgtname);
1342 return (-1); /* errno is set for us */
1344 if (mdb_ctf_type_encoding(modid, &mod_encoding) != 0) {
1345 mdb_ctf_warn(flags, "couldn't determine encoding of "
1346 "mdb module type %s\n", mdbtypename);
1347 return (-1); /* errno is set for us */
1350 if (modkind == CTF_K_INTEGER) {
1351 if ((tgt_encoding.cte_format & CTF_INT_SIGNED) !=
1352 (mod_encoding.cte_format & CTF_INT_SIGNED)) {
1353 mdb_ctf_warn(flags,
1354 "signedness mismatch between type "
1355 "%s (%s) and mdb module type %s\n",
1356 typename, tgtname, mdbtypename);
1357 return (set_errno(EMDB_INCOMPAT));
1359 signed_int =
1360 ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 0);
1361 } else if (tgt_encoding.cte_format != mod_encoding.cte_format) {
1362 mdb_ctf_warn(flags,
1363 "encoding mismatch (%#x != %#x) between type "
1364 "%s (%s) and mdb module type %s\n",
1365 tgt_encoding.cte_format, mod_encoding.cte_format,
1366 typename, tgtname, mdbtypename);
1367 return (set_errno(EMDB_INCOMPAT));
1369 /* FALLTHROUGH */
1370 case CTF_K_POINTER:
1372 * If the sizes don't match we need to be tricky to make
1373 * sure that the caller gets the correct data.
1375 if (modsz < tgtsz) {
1376 mdb_ctf_warn(flags, "size of type %s (%s) is too "
1377 "large for mdb module type %s\n",
1378 typename, tgtname, mdbtypename);
1379 return (set_errno(EMDB_INCOMPAT));
1380 } else if (modsz > tgtsz) {
1381 /* BEGIN CSTYLED */
1383 * Fill modbuf with 1's for sign extension if target
1384 * buf is a signed integer and its value is negative.
1386 * S = sign bit (in most-significant byte)
1388 * BIG ENDIAN DATA
1389 * +--------+--------+--------+--------+
1390 * |S | | | |
1391 * +--------+--------+--------+--------+
1392 * 0 1 ... sz-1 sz
1394 * LITTLE ENDIAN DATA
1395 * +--------+--------+--------+--------+
1396 * | | | |S |
1397 * +--------+--------+--------+--------+
1398 * 0 1 ... sz-1 sz
1400 /* END CSTYLED */
1401 #ifdef _BIG_ENDIAN
1402 if (signed_int && (tgtbuf[0] & 0x80) != 0)
1403 #else
1404 if (signed_int && (tgtbuf[tgtsz - 1] & 0x80) != 0)
1405 #endif
1406 (void) memset(modbuf, 0xFF, modsz);
1407 else
1408 bzero(modbuf, modsz);
1409 #ifdef _BIG_ENDIAN
1410 bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz);
1411 #else
1412 bcopy(tgtbuf, modbuf, tgtsz);
1413 #endif
1414 } else {
1415 bcopy(tgtbuf, modbuf, modsz);
1418 return (0);
1420 case CTF_K_ENUM:
1421 if (modsz != tgtsz || modsz != sizeof (int)) {
1422 mdb_ctf_warn(flags, "unexpected size of type %s (%s)\n",
1423 typename, tgtname);
1424 return (set_errno(EMDB_INCOMPAT));
1428 * Default to the same value as in the target.
1430 bcopy(tgtbuf, modbuf, sizeof (int));
1432 /* LINTED */
1433 i = *(int *)tgtbuf;
1435 /* LINTED */
1436 ev.ev_modbuf = (int *)modbuf;
1437 ev.ev_name = mdb_ctf_enum_name(tgtid, i);
1438 if (ev.ev_name == NULL) {
1439 mdb_ctf_warn(flags,
1440 "unexpected value %u of enum type %s (%s)\n",
1441 i, typename, tgtname);
1442 return (set_errno(EMDB_INCOMPAT));
1445 ret = mdb_ctf_enum_iter(modid, enum_cb, &ev);
1446 if (ret == 0) {
1447 /* value not found */
1448 mdb_ctf_warn(flags,
1449 "unexpected value %s (%u) of enum type %s (%s)\n",
1450 ev.ev_name, i, typename, tgtname);
1451 return (set_errno(EMDB_INCOMPAT));
1452 } else if (ret == 1) {
1453 /* value found */
1454 return (0);
1455 } else if (ret == -1) {
1456 mdb_ctf_warn(flags, "could not iterate enum %s (%s)\n",
1457 typename, tgtname);
1459 return (ret);
1461 case CTF_K_STRUCT:
1462 mbr.m_modbuf = modbuf;
1463 mbr.m_tgtbuf = tgtbuf;
1464 mbr.m_tgtid = tgtid;
1465 mbr.m_flags = flags;
1466 mbr.m_tgtname = typename;
1468 return (mdb_ctf_member_iter(modid, member_cb, &mbr));
1470 case CTF_K_UNION:
1471 mbr.m_modbuf = modbuf;
1472 mbr.m_tgtbuf = tgtbuf;
1473 mbr.m_tgtid = tgtid;
1474 mbr.m_flags = flags;
1475 mbr.m_tgtname = typename;
1478 * Not all target union members need to be present in the
1479 * mdb type. If there is only a single union member in the
1480 * mdb type, its actual type does not need to match with
1481 * its target's type. On the other hand, if more than one
1482 * union members are specified in the mdb type, their types
1483 * must match with the types of their relevant union members
1484 * of the target union.
1486 mod_members = mdb_ctf_num_members(modid);
1487 if (mod_members == 1) {
1488 return (mdb_ctf_member_iter(modid, member_cb, &mbr));
1489 } else if (mod_members > 1) {
1490 if (mdb_ctf_member_iter(modid, type_equals_cb,
1491 &tgtid)) {
1492 mdb_ctf_warn(flags,
1493 "inexact match for union %s (%s)\n",
1494 typename, tgtname);
1495 return (set_errno(EMDB_INCOMPAT));
1499 * From the check above we know that the members
1500 * which are present in the mdb type are equal to
1501 * the types in the target. Thus, the member_cb
1502 * callback below will not move anything around and
1503 * it is equivalent to:
1505 * bcopy(tgtbuf, modbuf, MAX(module member's sizes))
1507 return (mdb_ctf_member_iter(modid, member_cb, &mbr));
1508 } else {
1510 * We either got 0 or -1. In any case that number
1511 * should be returned right away. For the error
1512 * case of -1, errno has been set for us.
1514 return (mod_members);
1517 case CTF_K_ARRAY:
1518 if (mdb_ctf_array_info(tgtid, &tar) != 0) {
1519 mdb_ctf_warn(flags,
1520 "couldn't get array info for %s (%s)\n",
1521 typename, tgtname);
1522 return (-1); /* errno is set for us */
1524 if (mdb_ctf_array_info(modid, &mar) != 0) {
1525 mdb_ctf_warn(flags,
1526 "couldn't get array info for mdb module type %s\n",
1527 mdbtypename);
1528 return (-1); /* errno is set for us */
1531 if (tar.mta_nelems != mar.mta_nelems) {
1532 mdb_ctf_warn(flags,
1533 "unexpected array size (%u) for type %s (%s)\n",
1534 tar.mta_nelems, typename, tgtname);
1535 return (set_errno(EMDB_INCOMPAT));
1538 if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) {
1539 mdb_ctf_warn(flags, "couldn't determine type size of "
1540 "mdb module type %s\n", mdbtypename);
1541 return (-1); /* errno is set for us */
1543 if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) {
1544 mdb_ctf_warn(flags,
1545 "couldn't determine size of %s (%s)\n",
1546 typename, tgtname);
1547 return (-1); /* errno is set for us */
1550 for (i = 0; i < tar.mta_nelems; i++) {
1551 ret = vread_helper(mar.mta_contents, modbuf + i * modsz,
1552 tar.mta_contents, tgtbuf + i * tgtsz,
1553 tgtname, flags);
1555 if (ret != 0)
1556 return (ret);
1559 return (0);
1562 mdb_ctf_warn(flags, "unsupported kind %d for type %s (%s)\n",
1563 modkind, typename, tgtname);
1564 return (set_errno(EMDB_INCOMPAT));
1568 * Like mdb_vread(), mdb_ctf_vread() is used to read from the target's
1569 * virtual address space. However, mdb_ctf_vread() can be used to safely
1570 * read a complex type (e.g. a struct) from the target, even if MDB was compiled
1571 * against a different definition of that type (e.g. when debugging a crash
1572 * dump from an older release).
1574 * Callers can achieve this by defining their own type which corresponds to the
1575 * type in the target, but contains only the members that the caller requires.
1576 * Using the CTF type information embedded in the target, mdb_ctf_vread will
1577 * find the required members in the target and fill in the caller's structure.
1578 * The members are located by name, and their types are verified to be
1579 * compatible.
1581 * By convention, the caller will declare a type with the name "mdb_<type>",
1582 * where <type> is the name of the type in the target (e.g. mdb_zio_t). This
1583 * type will contain the members that the caller is interested in. For example:
1585 * typedef struct mdb_zio {
1586 * enum zio_type io_type;
1587 * uintptr_t io_waiter;
1588 * struct {
1589 * struct {
1590 * uintptr_t list_next;
1591 * } list_head;
1592 * } io_parent_list;
1593 * int io_error;
1594 * } mdb_zio_t;
1596 * mdb_zio_t zio;
1597 * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0);
1599 * If a given MDB module has different dcmds or walkers that need to read
1600 * different members from the same struct, then different "mdb_" types
1601 * should be declared for each caller. By convention, these types should
1602 * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t
1603 * for ::findstack. If the MDB module is compiled from several source files,
1604 * one must be especially careful to not define different types with the
1605 * same name in different source files, because the compiler can not detect
1606 * this error.
1608 * Enums will also be translated by name, so the mdb module will receive
1609 * the enum value it expects even if the target has renumbered the enum.
1610 * Warning: it will therefore only work with enums are only used to store
1611 * legitimate enum values (not several values or-ed together).
1613 * By default, if mdb_ctf_vread() can not find any members or enum values,
1614 * it will print a descriptive message (with mdb_warn()) and fail.
1615 * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message.
1616 * Additional flags can be used to ignore specific types of translation
1617 * failure, but should be used with caution, because they will silently leave
1618 * the caller's buffer uninitialized.
1621 mdb_ctf_vread(void *modbuf, const char *target_typename,
1622 const char *mdb_typename, uintptr_t addr, uint_t flags)
1624 ctf_file_t *mfp;
1625 ctf_id_t mid;
1626 void *tgtbuf;
1627 size_t size;
1628 mdb_ctf_id_t tgtid;
1629 mdb_ctf_id_t modid;
1630 mdb_module_t *mod;
1632 if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
1633 mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
1634 mod->mod_name);
1635 return (set_errno(EMDB_NOCTF));
1638 if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) {
1639 mdb_ctf_warn(flags, "couldn't find ctf data for "
1640 "type %s in mdb module %s\n",
1641 mdb_typename, mod->mod_name);
1642 return (set_errno(ctf_to_errno(ctf_errno(mfp))));
1645 set_ctf_id(&modid, mfp, mid);
1647 if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) {
1648 mdb_ctf_warn(flags,
1649 "couldn't find type %s in target's ctf data\n",
1650 target_typename);
1651 return (set_errno(EMDB_NOCTF));
1655 * Read the data out of the target's address space.
1657 if ((size = mdb_ctf_type_size(tgtid)) == -1UL) {
1658 mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
1659 target_typename);
1660 return (-1); /* errno is set for us */
1663 tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
1665 if (mdb_vread(tgtbuf, size, addr) < 0) {
1666 mdb_ctf_warn(flags, "couldn't read %s from %p\n",
1667 target_typename, addr);
1668 return (-1); /* errno is set for us */
1671 return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags));
1675 * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
1676 * of the target's type vs the mdb module's type. Use with complicated
1677 * types (e.g. structs) may result in unnecessary failure if a member of
1678 * the struct has been changed in the target, but is not actually needed
1679 * by the mdb module. Use mdb_lookup_by_name() + mdb_ctf_vread() to
1680 * avoid this problem.
1683 mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
1685 GElf_Sym sym;
1687 if (mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, name, &sym) != 0) {
1688 mdb_ctf_warn(flags, "couldn't find symbol %s\n", name);
1689 return (-1); /* errno is set for us */
1692 return (mdb_ctf_vread(buf, typename, typename, sym.st_value, flags));
1695 ctf_file_t *
1696 mdb_ctf_bufopen(const void *ctf_va, size_t ctf_size, const void *sym_va,
1697 Shdr *symhdr, const void *str_va, Shdr *strhdr, int *errp)
1699 ctf_sect_t ctdata, symtab, strtab;
1701 ctdata.cts_name = ".SUNW_ctf";
1702 ctdata.cts_type = SHT_PROGBITS;
1703 ctdata.cts_flags = 0;
1704 ctdata.cts_data = ctf_va;
1705 ctdata.cts_size = ctf_size;
1706 ctdata.cts_entsize = 1;
1707 ctdata.cts_offset = 0;
1709 symtab.cts_name = ".symtab";
1710 symtab.cts_type = symhdr->sh_type;
1711 symtab.cts_flags = symhdr->sh_flags;
1712 symtab.cts_data = sym_va;
1713 symtab.cts_size = symhdr->sh_size;
1714 symtab.cts_entsize = symhdr->sh_entsize;
1715 symtab.cts_offset = symhdr->sh_offset;
1717 strtab.cts_name = ".strtab";
1718 strtab.cts_type = strhdr->sh_type;
1719 strtab.cts_flags = strhdr->sh_flags;
1720 strtab.cts_data = str_va;
1721 strtab.cts_size = strhdr->sh_size;
1722 strtab.cts_entsize = strhdr->sh_entsize;
1723 strtab.cts_offset = strhdr->sh_offset;
1725 return (ctf_bufopen(&ctdata, &symtab, &strtab, errp));
1729 mdb_ctf_synthetics_init(void)
1731 int err;
1733 if ((mdb.m_synth = ctf_create(&err)) == NULL)
1734 return (set_errno(ctf_to_errno(err)));
1736 return (0);
1739 void
1740 mdb_ctf_synthetics_fini(void)
1742 if (mdb.m_synth == NULL)
1743 return;
1745 ctf_close(mdb.m_synth);
1746 mdb.m_synth = NULL;
1750 mdb_ctf_synthetics_create_base(int kind)
1752 const synth_intrinsic_t *synp;
1753 const synth_typedef_t *sytp;
1754 int err;
1755 ctf_id_t id;
1756 ctf_file_t *cp = mdb.m_synth;
1758 if (mdb.m_synth == NULL) {
1759 mdb_printf("synthetic types disabled: ctf create failed\n");
1760 return (1);
1763 switch (kind) {
1764 case SYNTHETIC_ILP32:
1765 synp = synth_builtins32;
1766 sytp = synth_typedefs32;
1767 break;
1768 case SYNTHETIC_LP64:
1769 synp = synth_builtins64;
1770 sytp = synth_typedefs64;
1771 break;
1772 default:
1773 mdb_dprintf(MDB_DBG_CTF, "invalid type of intrinsic: %d\n",
1774 kind);
1775 return (1);
1778 err = 0;
1779 for (; synp->syn_name != NULL; synp++) {
1780 if (synp->syn_kind == CTF_K_INTEGER) {
1781 err = ctf_add_integer(cp, CTF_ADD_ROOT, synp->syn_name,
1782 &synp->syn_enc);
1783 } else {
1784 err = ctf_add_float(cp, CTF_ADD_ROOT, synp->syn_name,
1785 &synp->syn_enc);
1788 if (err == CTF_ERR) {
1789 mdb_dprintf(MDB_DBG_CTF, "couldn't add synthetic "
1790 "type: %s\n", synp->syn_name);
1791 goto discard;
1795 if (ctf_update(cp) == CTF_ERR) {
1796 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
1797 goto discard;
1800 for (; sytp->syt_src != NULL; sytp++) {
1801 id = ctf_lookup_by_name(cp, sytp->syt_src);
1802 if (id == CTF_ERR) {
1803 mdb_dprintf(MDB_DBG_CTF, "cailed to lookup %s: %s\n",
1804 sytp->syt_src, ctf_errmsg(ctf_errno(cp)));
1805 goto discard;
1807 if (ctf_add_typedef(cp, CTF_ADD_ROOT, sytp->syt_targ, id) ==
1808 CTF_ERR) {
1809 mdb_dprintf(MDB_DBG_CTF, "couldn't add typedef %s "
1810 "%s: %s\n", sytp->syt_targ, sytp->syt_src,
1811 ctf_errmsg(ctf_errno(cp)));
1812 goto discard;
1816 if (ctf_update(cp) == CTF_ERR) {
1817 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
1818 goto discard;
1821 return (0);
1823 discard:
1824 err = set_errno(ctf_to_errno(ctf_errno(cp)));
1825 (void) ctf_discard(cp);
1826 return (err);
1830 mdb_ctf_synthetics_reset(void)
1832 mdb_ctf_synthetics_fini();
1833 return (mdb_ctf_synthetics_init());
1837 mdb_ctf_add_typedef(const char *name, const mdb_ctf_id_t *p, mdb_ctf_id_t *new)
1839 ctf_id_t rid;
1840 mdb_ctf_id_t tid;
1841 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
1843 if (mdb.m_synth == NULL) {
1844 mdb_printf("synthetic types disabled: ctf create failed\n");
1845 return (1);
1848 if (mdb_ctf_lookup_by_name(name, &tid) == 0) {
1849 mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1850 "with that name already exists\n", name);
1851 return (set_errno(EEXIST));
1854 rid = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
1855 if (rid == CTF_ERR) {
1856 mdb_dprintf(MDB_DBG_CTF, "failed to add reference type: %s\n",
1857 ctf_errmsg(ctf_errno(mdb.m_synth)));
1858 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1860 rid = ctf_add_typedef(mdb.m_synth, CTF_ADD_ROOT, name, rid);
1861 if (rid == CTF_ERR) {
1862 mdb_dprintf(MDB_DBG_CTF, "failed to add typedef: %s",
1863 ctf_errmsg(ctf_errno(mdb.m_synth)));
1864 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1867 if (ctf_update(mdb.m_synth) == CTF_ERR) {
1868 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1869 ctf_errmsg(ctf_errno(mdb.m_synth)));
1870 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1873 if (new != NULL)
1874 set_ctf_id(new, mdb.m_synth, rid);
1876 return (0);
1880 mdb_ctf_add_struct(const char *name, mdb_ctf_id_t *rid)
1882 mdb_ctf_id_t tid;
1883 ctf_id_t id;
1885 if (mdb.m_synth == NULL) {
1886 mdb_printf("synthetic types disabled: ctf create failed\n");
1887 return (1);
1890 if (name != NULL && mdb_ctf_lookup_by_name(name, &tid) == 0) {
1891 mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1892 "with that name already exists\n", name);
1893 return (set_errno(EEXIST));
1896 if ((id = ctf_add_struct(mdb.m_synth, CTF_ADD_ROOT, name)) ==
1897 CTF_ERR) {
1898 mdb_dprintf(MDB_DBG_CTF, "failed to add struct: %s\n",
1899 ctf_errmsg(ctf_errno(mdb.m_synth)));
1900 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1903 if (ctf_update(mdb.m_synth) == CTF_ERR) {
1904 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1905 ctf_errmsg(ctf_errno(mdb.m_synth)));
1906 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1909 if (rid != NULL)
1910 set_ctf_id(rid, mdb.m_synth, id);
1912 return (0);
1916 mdb_ctf_add_union(const char *name, mdb_ctf_id_t *rid)
1918 mdb_ctf_id_t tid;
1919 ctf_id_t id;
1921 if (mdb.m_synth == NULL) {
1922 mdb_printf("synthetic types disabled: ctf create failed\n");
1923 return (1);
1926 if (name != NULL && mdb_ctf_lookup_by_name(name, &tid) == 0) {
1927 mdb_dprintf(MDB_DBG_CTF, "failed to add type %s: a type "
1928 "with that name already exists\n", name);
1929 return (set_errno(EEXIST));
1932 if ((id = ctf_add_union(mdb.m_synth, CTF_ADD_ROOT, name)) ==
1933 CTF_ERR) {
1934 mdb_dprintf(MDB_DBG_CTF, "failed to add union: %s\n",
1935 ctf_errmsg(ctf_errno(mdb.m_synth)));
1936 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1939 if (ctf_update(mdb.m_synth) == CTF_ERR) {
1940 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1941 ctf_errmsg(ctf_errno(mdb.m_synth)));
1942 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1945 if (rid != NULL)
1946 set_ctf_id(rid, mdb.m_synth, id);
1948 return (0);
1952 mdb_ctf_add_member(const mdb_ctf_id_t *p, const char *name,
1953 const mdb_ctf_id_t *mtype, mdb_ctf_id_t *rid)
1955 ctf_id_t id, mtid;
1956 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
1957 mdb_ctf_impl_t *mcim = (mdb_ctf_impl_t *)mtype;
1959 if (mdb.m_synth == NULL) {
1960 mdb_printf("synthetic types disabled: ctf create failed\n");
1961 return (DCMD_ERR);
1964 if (mcip->mci_fp != mdb.m_synth) {
1965 mdb_dprintf(MDB_DBG_CTF, "requested to add member to a type "
1966 "that wasn't created from a synthetic\n");
1967 return (set_errno(EINVAL));
1970 mtid = ctf_add_type(mdb.m_synth, mcim->mci_fp, mcim->mci_id);
1971 if (mtid == CTF_ERR) {
1972 mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
1973 ctf_errmsg(ctf_errno(mdb.m_synth)));
1974 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1977 if (ctf_update(mdb.m_synth) == CTF_ERR) {
1978 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1979 ctf_errmsg(ctf_errno(mdb.m_synth)));
1980 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1983 id = ctf_add_member(mdb.m_synth, mcip->mci_id, name, mtid);
1984 if (id == CTF_ERR) {
1985 mdb_dprintf(MDB_DBG_CTF, "failed to add member %s: %s\n",
1986 name, ctf_errmsg(ctf_errno(mdb.m_synth)));
1987 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1990 if (ctf_update(mdb.m_synth) == CTF_ERR) {
1991 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
1992 ctf_errmsg(ctf_errno(mdb.m_synth)));
1993 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
1996 if (rid != NULL)
1997 set_ctf_id(rid, mdb.m_synth, id);
1999 return (0);
2003 mdb_ctf_add_array(const mdb_ctf_arinfo_t *marp, mdb_ctf_id_t *rid)
2005 mdb_ctf_impl_t *mcip;
2006 ctf_arinfo_t car;
2007 ctf_id_t id;
2009 if (mdb.m_synth == NULL) {
2010 mdb_printf("synthetic types disabled: ctf create failed\n");
2011 return (1);
2014 car.ctr_nelems = marp->mta_nelems;
2016 mcip = (mdb_ctf_impl_t *)&marp->mta_contents;
2017 id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2018 if (id == CTF_ERR) {
2019 mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
2020 ctf_errmsg(ctf_errno(mdb.m_synth)));
2021 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2023 car.ctr_contents = id;
2025 mcip = (mdb_ctf_impl_t *)&marp->mta_index;
2026 id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2027 if (id == CTF_ERR) {
2028 mdb_dprintf(MDB_DBG_CTF, "failed to add member type: %s\n",
2029 ctf_errmsg(ctf_errno(mdb.m_synth)));
2030 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2032 car.ctr_index = id;
2034 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2035 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2036 ctf_errmsg(ctf_errno(mdb.m_synth)));
2037 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2040 id = ctf_add_array(mdb.m_synth, CTF_ADD_ROOT, &car);
2041 if (id == CTF_ERR) {
2042 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2043 ctf_errmsg(ctf_errno(mdb.m_synth)));
2044 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2047 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2048 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2049 ctf_errmsg(ctf_errno(mdb.m_synth)));
2050 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2053 if (rid != NULL)
2054 set_ctf_id(rid, mdb.m_synth, id);
2056 return (0);
2060 mdb_ctf_add_pointer(const mdb_ctf_id_t *p, mdb_ctf_id_t *rid)
2062 ctf_id_t id;
2063 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p;
2065 if (mdb.m_synth == NULL) {
2066 mdb_printf("synthetic types disabled: ctf create failed\n");
2067 return (1);
2070 id = ctf_add_type(mdb.m_synth, mcip->mci_fp, mcip->mci_id);
2071 if (id == CTF_ERR) {
2072 mdb_dprintf(MDB_DBG_CTF, "failed to add pointer type: %s\n",
2073 ctf_errmsg(ctf_errno(mdb.m_synth)));
2074 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2077 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2078 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2079 ctf_errmsg(ctf_errno(mdb.m_synth)));
2080 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2084 id = ctf_add_pointer(mdb.m_synth, CTF_ADD_ROOT, id);
2085 if (id == CTF_ERR) {
2086 mdb_dprintf(MDB_DBG_CTF, "failed to add pointer: %s\n",
2087 ctf_errmsg(ctf_errno(mdb.m_synth)));
2088 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2091 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2092 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2093 ctf_errmsg(ctf_errno(mdb.m_synth)));
2094 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2098 if (rid != NULL)
2099 set_ctf_id(rid, mdb.m_synth, id);
2101 return (0);
2105 mdb_ctf_type_delete(const mdb_ctf_id_t *id)
2107 int ret;
2109 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)id;
2111 if (mcip->mci_fp != mdb.m_synth) {
2112 mdb_warn("bad ctf_file_t, expected synth container\n");
2113 return (1);
2116 ret = ctf_delete_type(mcip->mci_fp, mcip->mci_id);
2117 if (ret != 0) {
2118 mdb_dprintf(MDB_DBG_CTF, "failed to delete synthetic type: %s",
2119 ctf_errmsg(ctf_errno(mdb.m_synth)));
2120 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2123 if (ctf_update(mdb.m_synth) == CTF_ERR) {
2124 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types: %s",
2125 ctf_errmsg(ctf_errno(mdb.m_synth)));
2126 return (set_errno(ctf_to_errno(ctf_errno(mdb.m_synth))));
2129 return (0);
2132 static int
2133 mdb_ctf_synthetics_file_cb(mdb_ctf_id_t id, void *arg)
2135 ctf_file_t *targ = arg;
2136 mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)&id;
2138 if (ctf_add_type(targ, mcip->mci_fp, mcip->mci_id) == CTF_ERR) {
2139 mdb_dprintf(MDB_DBG_CTF, "failed to add type %d: %s\n",
2140 mcip->mci_id, ctf_errmsg(ctf_errno(mcip->mci_fp)));
2141 return (set_errno(ctf_to_errno(ctf_errno(mcip->mci_fp))));
2144 return (0);
2148 mdb_ctf_synthetics_from_file(const char *file)
2150 ctf_file_t *fp, *syn = mdb.m_synth;
2151 int ret;
2152 type_iter_t ti;
2154 if (syn == NULL) {
2155 mdb_warn("synthetic types disabled: ctf create failed\n");
2156 return (1);
2159 if ((fp = mdb_ctf_open(file, &ret)) == NULL) {
2160 mdb_warn("failed to parse ctf data in %s: %s\n", file,
2161 ctf_errmsg(ret));
2162 return (1);
2165 ret = DCMD_OK;
2166 ti.ti_fp = fp;
2167 ti.ti_arg = syn;
2168 ti.ti_cb = mdb_ctf_synthetics_file_cb;
2169 if (ctf_type_iter(fp, type_iter_cb, &ti) == CTF_ERR) {
2170 ret = set_errno(ctf_to_errno(ctf_errno(fp)));
2171 mdb_warn("failed to add types");
2172 goto cleanup;
2175 if (ctf_update(syn) == CTF_ERR) {
2176 mdb_dprintf(MDB_DBG_CTF, "failed to update synthetic types\n");
2177 ret = set_errno(ctf_to_errno(ctf_errno(fp)));
2180 cleanup:
2181 ctf_close(fp);
2182 if (ret != 0)
2183 (void) ctf_discard(syn);
2184 return (ret);
2188 mdb_ctf_synthetics_to_file(const char *file)
2190 int err;
2191 ctf_file_t *fp = mdb.m_synth;
2193 if (fp == NULL) {
2194 mdb_warn("synthetic types are disabled, not writing "
2195 "anything\n");
2196 return (DCMD_ERR);
2199 err = mdb_ctf_write(file, fp);
2200 if (err != 0) {
2201 if (err == CTF_ERR)
2202 (void) set_errno(ctf_to_errno(ctf_errno(fp)));
2203 else
2204 (void) set_errno(err);
2205 err = DCMD_ERR;
2206 } else {
2207 err = DCMD_OK;
2210 return (err);