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