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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 #ifdef HAVE_NBTOOL_CONFIG_H
23 #include "nbtool_config.h"
24 #endif
25
26 /*
27 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31 #include <ctf_impl.h>
32
33 void
ctf_get_ctt_index(const ctf_file_t * fp,const void * v,uint_t * indexp,uint_t * typep,int * ischildp)34 ctf_get_ctt_index(const ctf_file_t *fp, const void *v, uint_t *indexp,
35 uint_t *typep, int *ischildp)
36 {
37 uint_t index, type;
38 int ischild;
39
40 if (fp->ctf_version == CTF_VERSION_2) {
41 const struct ctf_type_v2 *ctt = v;
42
43 type = ctt->ctt_type;
44 index = CTF_V2_TYPE_TO_INDEX(ctt->ctt_type);
45 ischild = CTF_V2_TYPE_ISCHILD(ctt->ctt_type);
46 } else {
47 const struct ctf_type_v3 *ctt = v;
48
49 type = ctt->ctt_type;
50 index = CTF_V3_TYPE_TO_INDEX(ctt->ctt_type);
51 ischild = CTF_V3_TYPE_ISCHILD(ctt->ctt_type);
52 }
53
54 if (indexp != NULL)
55 *indexp = index;
56 if (typep != NULL)
57 *typep = type;
58 if (ischildp != NULL)
59 *ischildp = ischild;
60 }
61
62 void
ctf_get_ctt_info(const ctf_file_t * fp,const void * v,uint_t * kindp,uint_t * vlenp,uint_t * isrootp)63 ctf_get_ctt_info(const ctf_file_t *fp, const void *v, uint_t *kindp,
64 uint_t *vlenp, uint_t *isrootp)
65 {
66 uint_t kind, vlen;
67 int isroot;
68
69 if (fp->ctf_version == CTF_VERSION_2) {
70 const struct ctf_type_v2 *ctt = v;
71
72 kind = CTF_V2_INFO_KIND(ctt->ctt_info);
73 vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
74 isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
75 } else {
76 const struct ctf_type_v3 *ctt = v;
77
78 kind = CTF_V3_INFO_KIND(ctt->ctt_info);
79 vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
80 isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
81 }
82
83 if (kindp != NULL)
84 *kindp = kind;
85 if (vlenp != NULL)
86 *vlenp = vlen;
87 if (isrootp != NULL)
88 *isrootp = isroot;
89 }
90
91 ssize_t
ctf_get_ctt_size(const ctf_file_t * fp,const void * v,ssize_t * sizep,ssize_t * incrementp)92 ctf_get_ctt_size(const ctf_file_t *fp, const void *v, ssize_t *sizep,
93 ssize_t *incrementp)
94 {
95 ssize_t size, increment;
96
97 if (fp->ctf_version == CTF_VERSION_2) {
98 const struct ctf_type_v2 *ctt = v;
99
100 if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
101 size = (size_t)CTF_TYPE_LSIZE(ctt);
102 increment = sizeof (struct ctf_type_v2);
103 } else {
104 size = ctt->ctt_size;
105 increment = sizeof (struct ctf_stype_v2);
106 }
107 } else {
108 const struct ctf_type_v3 *ctt = v;
109
110 if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
111 size = (size_t)CTF_TYPE_LSIZE(ctt);
112 increment = sizeof (struct ctf_type_v3);
113 } else {
114 size = ctt->ctt_size;
115 increment = sizeof (struct ctf_stype_v3);
116 }
117 }
118
119 if (sizep)
120 *sizep = size;
121 if (incrementp)
122 *incrementp = increment;
123
124 return (size);
125 }
126
127 /*
128 * Fetch info for a struct or union member.
129 */
130 void
ctf_get_ctm_info(const ctf_file_t * fp,const void * v,ssize_t size,ssize_t * incrementp,uint_t * typep,ulong_t * offsetp,const char ** namep)131 ctf_get_ctm_info(const ctf_file_t *fp, const void *v, ssize_t size,
132 ssize_t *incrementp, uint_t *typep, ulong_t *offsetp, const char **namep)
133 {
134 size_t increment;
135 ulong_t offset;
136 uint_t name, type;
137
138 if (fp->ctf_version == CTF_VERSION_2) {
139 if (size < CTF_V2_LSTRUCT_THRESH) {
140 const struct ctf_member_v2 *ctm = v;
141
142 name = ctm->ctm_name;
143 type = ctm->ctm_type;
144 offset = ctm->ctm_offset;
145 increment = sizeof(*ctm);
146 } else {
147 const struct ctf_lmember_v2 *ctlm = v;
148
149 name = ctlm->ctlm_name;
150 type = ctlm->ctlm_type;
151 offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
152 increment = sizeof(*ctlm);
153 }
154 } else {
155 if (size < CTF_V3_LSTRUCT_THRESH) {
156 const struct ctf_member_v3 *ctm = v;
157
158 name = ctm->ctm_name;
159 type = ctm->ctm_type;
160 offset = ctm->ctm_offset;
161 increment = sizeof(*ctm);
162 } else {
163 const struct ctf_lmember_v3 *ctlm = v;
164
165 name = ctlm->ctlm_name;
166 type = ctlm->ctlm_type;
167 offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
168 increment = sizeof(*ctlm);
169 }
170 }
171
172 if (incrementp != NULL)
173 *incrementp = increment;
174 if (typep != NULL)
175 *typep = type;
176 if (offsetp != NULL)
177 *offsetp = offset;
178 if (namep != NULL)
179 *namep = ctf_strraw(fp, name);
180 }
181
182 /*
183 * Iterate over the members of a STRUCT or UNION. We pass the name, member
184 * type, and offset of each member to the specified callback function.
185 */
186 int
ctf_member_iter(ctf_file_t * fp,ctf_id_t type,ctf_member_f * func,void * arg)187 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
188 {
189 ctf_file_t *ofp = fp;
190 const void *tp;
191 ssize_t size, increment;
192 uint_t kind, n, vlen;
193 int rc;
194
195 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
196 return (CTF_ERR); /* errno is set for us */
197
198 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
199 return (CTF_ERR); /* errno is set for us */
200
201 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
202 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
203
204 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
205 return (ctf_set_errno(ofp, ECTF_NOTSOU));
206
207 const char *mp = (const char *)((uintptr_t)tp + increment);
208
209 for (n = vlen; n != 0; n--, mp += increment) {
210 const char *name;
211 ulong_t offset;
212 uint_t xtype;
213
214 ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset,
215 &name);
216 if ((rc = func(name, xtype, offset, arg)) != 0)
217 return (rc);
218 }
219
220 return (0);
221 }
222
223 /*
224 * Iterate over the members of an ENUM. We pass the string name and associated
225 * integer value of each enum element to the specified callback function.
226 */
227 int
ctf_enum_iter(ctf_file_t * fp,ctf_id_t type,ctf_enum_f * func,void * arg)228 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
229 {
230 ctf_file_t *ofp = fp;
231 const void *tp;
232 const ctf_enum_t *ep;
233 ssize_t increment;
234 uint_t kind, n, vlen;
235 int rc;
236
237 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
238 return (CTF_ERR); /* errno is set for us */
239
240 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
241 return (CTF_ERR); /* errno is set for us */
242
243 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
244 if (kind != CTF_K_ENUM)
245 return (ctf_set_errno(ofp, ECTF_NOTENUM));
246
247 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
248
249 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
250
251 for (n = vlen; n != 0; n--, ep++) {
252 const char *name = ctf_strptr(fp, ep->cte_name);
253 if ((rc = func(name, ep->cte_value, arg)) != 0)
254 return (rc);
255 }
256
257 return (0);
258 }
259
260 /*
261 * Iterate over every root (user-visible) type in the given CTF container.
262 * We pass the type ID of each type to the specified callback function.
263 */
264 int
ctf_type_iter(ctf_file_t * fp,ctf_type_f * func,void * arg)265 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
266 {
267 ctf_id_t id, max = fp->ctf_typemax;
268 int rc, child = (fp->ctf_flags & LCTF_CHILD);
269 uint_t isroot;
270
271 for (id = 1; id <= max; id++) {
272 const void *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
273 ctf_get_ctt_info(fp, tp, NULL, NULL, &isroot);
274 if (isroot &&
275 (rc = func(LCTF_INDEX_TO_TYPE(fp, id, child), arg)) != 0)
276 return (rc);
277 }
278
279 return (0);
280 }
281
282 /*
283 * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
284 * RESTRICT nodes until we reach a "base" type node. This is useful when
285 * we want to follow a type ID to a node that has members or a size. To guard
286 * against infinite loops, we implement simplified cycle detection and check
287 * each link against itself, the previous node, and the topmost node.
288 */
289 ctf_id_t
ctf_type_resolve(ctf_file_t * fp,ctf_id_t type)290 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
291 {
292 ctf_id_t prev = type, otype = type;
293 ctf_file_t *ofp = fp;
294 const void *tp;
295 uint_t kind, ctype;
296
297 while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
298 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
299 switch (kind) {
300 case CTF_K_TYPEDEF:
301 case CTF_K_VOLATILE:
302 case CTF_K_CONST:
303 case CTF_K_RESTRICT:
304 ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
305 if (ctype == type || ctype == otype || ctype == prev) {
306 ctf_dprintf("type %ld cycle detected\n", otype);
307 return (ctf_set_errno(ofp, ECTF_CORRUPT));
308 }
309 prev = type;
310 type = ctype;
311 break;
312 default:
313 return (type);
314 }
315 }
316
317 return (CTF_ERR); /* errno is set for us */
318 }
319
320 /*
321 * Lookup the given type ID and print a string name for it into buf. Return
322 * the actual number of bytes (not including \0) needed to format the name.
323 */
324 static ssize_t
ctf_type_qlname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * qname)325 ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
326 const char *qname)
327 {
328 ctf_decl_t cd;
329 ctf_decl_node_t *cdp;
330 ctf_decl_prec_t prec, lp, rp;
331 int ptr, arr;
332 uint_t k;
333
334 if (fp == NULL && type == CTF_ERR)
335 return (-1); /* simplify caller code by permitting CTF_ERR */
336
337 ctf_decl_init(&cd, buf, len);
338 ctf_decl_push(&cd, fp, type);
339
340 if (cd.cd_err != 0) {
341 ctf_decl_fini(&cd);
342 return (ctf_set_errno(fp, cd.cd_err));
343 }
344
345 /*
346 * If the type graph's order conflicts with lexical precedence order
347 * for pointers or arrays, then we need to surround the declarations at
348 * the corresponding lexical precedence with parentheses. This can
349 * result in either a parenthesized pointer (*) as in int (*)() or
350 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
351 */
352 ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
353 arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
354
355 rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
356 lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
357
358 k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
359
360 for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
361 for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
362 cdp != NULL; cdp = ctf_list_next(cdp)) {
363
364 ctf_file_t *rfp = fp;
365 const void *tp = ctf_lookup_by_id(&rfp, cdp->cd_type);
366 const char *name = ctf_type_rname(rfp, tp);
367
368 if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
369 ctf_decl_sprintf(&cd, " ");
370
371 if (lp == prec) {
372 ctf_decl_sprintf(&cd, "(");
373 lp = -1;
374 }
375
376 switch (cdp->cd_kind) {
377 case CTF_K_INTEGER:
378 case CTF_K_FLOAT:
379 case CTF_K_TYPEDEF:
380 if (qname != NULL)
381 ctf_decl_sprintf(&cd, "%s`", qname);
382 ctf_decl_sprintf(&cd, "%s", name);
383 break;
384 case CTF_K_POINTER:
385 ctf_decl_sprintf(&cd, "*");
386 break;
387 case CTF_K_ARRAY:
388 ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
389 break;
390 case CTF_K_FUNCTION:
391 ctf_decl_sprintf(&cd, "()");
392 break;
393 case CTF_K_STRUCT:
394 case CTF_K_FORWARD:
395 ctf_decl_sprintf(&cd, "struct ");
396 if (qname != NULL)
397 ctf_decl_sprintf(&cd, "%s`", qname);
398 ctf_decl_sprintf(&cd, "%s", name);
399 break;
400 case CTF_K_UNION:
401 ctf_decl_sprintf(&cd, "union ");
402 if (qname != NULL)
403 ctf_decl_sprintf(&cd, "%s`", qname);
404 ctf_decl_sprintf(&cd, "%s", name);
405 break;
406 case CTF_K_ENUM:
407 ctf_decl_sprintf(&cd, "enum ");
408 if (qname != NULL)
409 ctf_decl_sprintf(&cd, "%s`", qname);
410 ctf_decl_sprintf(&cd, "%s", name);
411 break;
412 case CTF_K_VOLATILE:
413 ctf_decl_sprintf(&cd, "volatile");
414 break;
415 case CTF_K_CONST:
416 ctf_decl_sprintf(&cd, "const");
417 break;
418 case CTF_K_RESTRICT:
419 ctf_decl_sprintf(&cd, "restrict");
420 break;
421 }
422
423 k = cdp->cd_kind;
424 }
425
426 if (rp == prec)
427 ctf_decl_sprintf(&cd, ")");
428 }
429
430 if (cd.cd_len >= len)
431 (void) ctf_set_errno(fp, ECTF_NAMELEN);
432
433 ctf_decl_fini(&cd);
434 return (cd.cd_len);
435 }
436
437 ssize_t
ctf_type_lname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)438 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
439 {
440 return (ctf_type_qlname(fp, type, buf, len, NULL));
441 }
442
443 /*
444 * Lookup the given type ID and print a string name for it into buf. If buf
445 * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
446 */
447 char *
ctf_type_name(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)448 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
449 {
450 ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
451 return (rv >= 0 && rv < len ? buf : NULL);
452 }
453
454 char *
ctf_type_qname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * qname)455 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
456 const char *qname)
457 {
458 ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
459 return (rv >= 0 && rv < len ? buf : NULL);
460 }
461
462 const char *
ctf_type_rname(ctf_file_t * fp,const void * v)463 ctf_type_rname(ctf_file_t *fp, const void *v)
464 {
465 uint_t name;
466
467 if (fp->ctf_version == CTF_VERSION_2) {
468 const struct ctf_type_v2 *ctt = v;
469
470 name = ctt->ctt_name;
471 } else {
472 const struct ctf_type_v3 *ctt = v;
473
474 name = ctt->ctt_name;
475 }
476
477 return (ctf_strptr(fp, name));
478 }
479
480 /*
481 * Resolve the type down to a base type node, and then return the size
482 * of the type storage in bytes.
483 */
484 ssize_t
ctf_type_size(ctf_file_t * fp,ctf_id_t type)485 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
486 {
487 const void *tp;
488 ssize_t size;
489 ctf_arinfo_t ar;
490 uint_t kind;
491
492 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
493 return (-1); /* errno is set for us */
494
495 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
496 return (-1); /* errno is set for us */
497
498 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
499
500 switch (kind) {
501 case CTF_K_POINTER:
502 return (fp->ctf_dmodel->ctd_pointer);
503
504 case CTF_K_FUNCTION:
505 return (0); /* function size is only known by symtab */
506
507 case CTF_K_ENUM:
508 return (fp->ctf_dmodel->ctd_int);
509
510 case CTF_K_ARRAY:
511 /*
512 * Array size is not directly returned by stabs data. Instead,
513 * it defines the element type and requires the user to perform
514 * the multiplication. If ctf_get_ctt_size() returns zero, the
515 * current version of ctfconvert does not compute member sizes
516 * and we compute the size here on its behalf.
517 */
518 if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
519 return (size);
520
521 if (ctf_array_info(fp, type, &ar) == CTF_ERR ||
522 (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR)
523 return (-1); /* errno is set for us */
524
525 return (size * ar.ctr_nelems);
526
527 default:
528 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
529 }
530 }
531
532 /*
533 * Resolve the type down to a base type node, and then return the alignment
534 * needed for the type storage in bytes.
535 */
536 ssize_t
ctf_type_align(ctf_file_t * fp,ctf_id_t type)537 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
538 {
539 const void *tp;
540 ctf_arinfo_t r;
541 uint_t kind, vlen;
542
543 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
544 return (-1); /* errno is set for us */
545
546 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
547 return (-1); /* errno is set for us */
548
549 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
550
551 switch (kind) {
552 case CTF_K_POINTER:
553 case CTF_K_FUNCTION:
554 return (fp->ctf_dmodel->ctd_pointer);
555
556 case CTF_K_ARRAY:
557 if (ctf_array_info(fp, type, &r) == CTF_ERR)
558 return (-1); /* errno is set for us */
559 return (ctf_type_align(fp, r.ctr_contents));
560
561 case CTF_K_STRUCT:
562 case CTF_K_UNION: {
563 uint_t n = vlen;
564 ssize_t size, increment;
565 size_t align = 0;
566 const void *vmp;
567
568 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
569 vmp = (const uchar_t *)tp + increment;
570
571 if (kind == CTF_K_STRUCT)
572 n = MIN(n, 1); /* only use first member for structs */
573
574 for (const char *mp = vmp; n != 0; n--, mp += increment) {
575 uint_t xtype;
576
577 ctf_get_ctm_info(fp, mp, size, &increment, &xtype,
578 NULL, NULL);
579 ssize_t am = ctf_type_align(fp, xtype);
580 align = MAX(align, am);
581 }
582
583 return (align);
584 }
585
586 case CTF_K_ENUM:
587 return (fp->ctf_dmodel->ctd_int);
588
589 default:
590 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
591 }
592 }
593
594 /*
595 * Return the kind (CTF_K_* constant) for the specified type ID.
596 */
597 int
ctf_type_kind(ctf_file_t * fp,ctf_id_t type)598 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
599 {
600 const void *tp;
601 uint_t kind;
602
603 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
604 return (CTF_ERR); /* errno is set for us */
605
606 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
607
608 return (kind);
609 }
610
611 /*
612 * If the type is one that directly references another type (such as POINTER),
613 * then return the ID of the type to which it refers.
614 */
615 ctf_id_t
ctf_type_reference(ctf_file_t * fp,ctf_id_t type)616 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
617 {
618 ctf_file_t *ofp = fp;
619 const void *tp;
620 uint_t ctype, kind;
621
622 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
623 return (CTF_ERR); /* errno is set for us */
624
625 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
626
627 switch (kind) {
628 case CTF_K_POINTER:
629 case CTF_K_TYPEDEF:
630 case CTF_K_VOLATILE:
631 case CTF_K_CONST:
632 case CTF_K_RESTRICT:
633 ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
634 return (ctype);
635 default:
636 return (ctf_set_errno(ofp, ECTF_NOTREF));
637 }
638 }
639
640 /*
641 * Find a pointer to type by looking in fp->ctf_ptrtab. If we can't find a
642 * pointer to the given type, see if we can compute a pointer to the type
643 * resulting from resolving the type down to its base type and use that
644 * instead. This helps with cases where the CTF data includes "struct foo *"
645 * but not "foo_t *" and the user accesses "foo_t *" in the debugger.
646 */
647 ctf_id_t
ctf_type_pointer(ctf_file_t * fp,ctf_id_t type)648 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
649 {
650 ctf_file_t *ofp = fp;
651 ctf_id_t ntype;
652
653 if (ctf_lookup_by_id(&fp, type) == NULL)
654 return (CTF_ERR); /* errno is set for us */
655
656 if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
657 return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
658
659 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
660 return (ctf_set_errno(ofp, ECTF_NOTYPE));
661
662 if (ctf_lookup_by_id(&fp, type) == NULL)
663 return (ctf_set_errno(ofp, ECTF_NOTYPE));
664
665 if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
666 return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
667
668 return (ctf_set_errno(ofp, ECTF_NOTYPE));
669 }
670
671 /*
672 * Return the encoding for the specified INTEGER or FLOAT.
673 */
674 int
ctf_type_encoding(ctf_file_t * fp,ctf_id_t type,ctf_encoding_t * ep)675 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
676 {
677 ctf_file_t *ofp = fp;
678 const void *tp;
679 ssize_t increment;
680 uint_t data, kind;
681
682 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
683 return (CTF_ERR); /* errno is set for us */
684
685 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
686 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
687
688 switch (kind) {
689 case CTF_K_INTEGER:
690 data = *(const uint_t *)((uintptr_t)tp + increment);
691 ep->cte_format = CTF_INT_ENCODING(data);
692 ep->cte_offset = CTF_INT_OFFSET(data);
693 ep->cte_bits = CTF_INT_BITS(data);
694 break;
695 case CTF_K_FLOAT:
696 data = *(const uint_t *)((uintptr_t)tp + increment);
697 ep->cte_format = CTF_FP_ENCODING(data);
698 ep->cte_offset = CTF_FP_OFFSET(data);
699 ep->cte_bits = CTF_FP_BITS(data);
700 break;
701 default:
702 return (ctf_set_errno(ofp, ECTF_NOTINTFP));
703 }
704
705 return (0);
706 }
707
708 int
ctf_type_cmp(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)709 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
710 {
711 int rval;
712
713 if (ltype < rtype)
714 rval = -1;
715 else if (ltype > rtype)
716 rval = 1;
717 else
718 rval = 0;
719
720 if (lfp == rfp)
721 return (rval);
722
723 if (LCTF_TYPE_ISPARENT(lfp, ltype) && lfp->ctf_parent != NULL)
724 lfp = lfp->ctf_parent;
725
726 if (LCTF_TYPE_ISPARENT(rfp, rtype) && rfp->ctf_parent != NULL)
727 rfp = rfp->ctf_parent;
728
729 if (lfp < rfp)
730 return (-1);
731
732 if (lfp > rfp)
733 return (1);
734
735 return (rval);
736 }
737
738 /*
739 * Return a boolean value indicating if two types are compatible integers or
740 * floating-pointer values. This function returns true if the two types are
741 * the same, or if they have the same ASCII name and encoding properties.
742 * This function could be extended to test for compatibility for other kinds.
743 */
744 int
ctf_type_compat(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)745 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
746 ctf_file_t *rfp, ctf_id_t rtype)
747 {
748 const void *ltp, *rtp;
749 ctf_encoding_t le, re;
750 ctf_arinfo_t la, ra;
751 uint_t lkind, rkind;
752
753 if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
754 return (1);
755
756 ltype = ctf_type_resolve(lfp, ltype);
757 lkind = ctf_type_kind(lfp, ltype);
758
759 rtype = ctf_type_resolve(rfp, rtype);
760 rkind = ctf_type_kind(rfp, rtype);
761
762 if (lkind != rkind ||
763 (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
764 (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
765 strcmp(ctf_type_rname(lfp, ltp), ctf_type_rname(rfp, rtp)) != 0)
766 return (0);
767
768 switch (lkind) {
769 case CTF_K_INTEGER:
770 case CTF_K_FLOAT:
771 return (ctf_type_encoding(lfp, ltype, &le) == 0 &&
772 ctf_type_encoding(rfp, rtype, &re) == 0 &&
773 memcmp(&le, &re, sizeof (ctf_encoding_t)) == 0);
774 case CTF_K_POINTER:
775 return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
776 rfp, ctf_type_reference(rfp, rtype)));
777 case CTF_K_ARRAY:
778 return (ctf_array_info(lfp, ltype, &la) == 0 &&
779 ctf_array_info(rfp, rtype, &ra) == 0 &&
780 la.ctr_nelems == ra.ctr_nelems && ctf_type_compat(
781 lfp, la.ctr_contents, rfp, ra.ctr_contents) &&
782 ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index));
783 case CTF_K_STRUCT:
784 case CTF_K_UNION:
785 return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
786 case CTF_K_ENUM:
787 case CTF_K_FORWARD:
788 return (1); /* no other checks required for these type kinds */
789 default:
790 return (0); /* should not get here since we did a resolve */
791 }
792 }
793
794 static int
_ctf_member_info(ctf_file_t * fp,ctf_id_t type,const char * name,ulong_t off,ctf_membinfo_t * mip)795 _ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, ulong_t off,
796 ctf_membinfo_t *mip)
797 {
798 ctf_file_t *ofp = fp;
799 const void *tp;
800 ssize_t size, increment;
801 uint_t kind, n, vlen;
802
803 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
804 return (CTF_ERR); /* errno is set for us */
805
806 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
807 return (CTF_ERR); /* errno is set for us */
808
809 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
810 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
811
812 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
813 return (ctf_set_errno(ofp, ECTF_NOTSOU));
814
815 const char *mp = (const char *)((uintptr_t)tp + increment);
816
817 for (n = vlen; n != 0; n--, mp += increment) {
818 const char *name1;
819 ulong_t offset;
820 uint_t xtype;
821
822 ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset,
823 &name1);
824 if (name1[0] == '\0' &&
825 _ctf_member_info(fp, xtype, name, offset + off, mip) == 0)
826 return (0);
827 if (strcmp(name1, name) == 0) {
828 mip->ctm_type = xtype;
829 mip->ctm_offset = offset + off;
830 return (0);
831 }
832 }
833
834 return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
835 }
836
837 /*
838 * Return the type and offset for a given member of a STRUCT or UNION.
839 */
840 int
ctf_member_info(ctf_file_t * fp,ctf_id_t type,const char * name,ctf_membinfo_t * mip)841 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
842 ctf_membinfo_t *mip)
843 {
844
845 return (_ctf_member_info(fp, type, name, 0, mip));
846 }
847
848 /*
849 * Return the array type, index, and size information for the specified ARRAY.
850 */
851 int
ctf_array_info(ctf_file_t * fp,ctf_id_t type,ctf_arinfo_t * arp)852 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
853 {
854 ctf_file_t *ofp = fp;
855 const void *ap, *tp;
856 ssize_t increment;
857 uint_t kind;
858
859 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
860 return (CTF_ERR); /* errno is set for us */
861
862 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
863
864 if (kind != CTF_K_ARRAY)
865 return (ctf_set_errno(ofp, ECTF_NOTARRAY));
866
867 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
868
869 ap = (const void *)((uintptr_t)tp + increment);
870 if (fp->ctf_version == CTF_VERSION_2) {
871 const struct ctf_array_v2 *ap2 = ap;
872
873 arp->ctr_contents = ap2->cta_contents;
874 arp->ctr_index = ap2->cta_index;
875 arp->ctr_nelems = ap2->cta_nelems;
876 } else {
877 const struct ctf_array_v3 *ap3 = ap;
878
879 arp->ctr_contents = ap3->cta_contents;
880 arp->ctr_index = ap3->cta_index;
881 arp->ctr_nelems = ap3->cta_nelems;
882 }
883
884 return (0);
885 }
886
887 /*
888 * Convert the specified value to the corresponding enum member name, if a
889 * matching name can be found. Otherwise NULL is returned.
890 */
891 const char *
ctf_enum_name(ctf_file_t * fp,ctf_id_t type,int value)892 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
893 {
894 ctf_file_t *ofp = fp;
895 const void *tp;
896 const ctf_enum_t *ep;
897 ssize_t increment;
898 uint_t kind, n, vlen;
899
900 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
901 return (NULL); /* errno is set for us */
902
903 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
904 return (NULL); /* errno is set for us */
905
906 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
907
908 if (kind != CTF_K_ENUM) {
909 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
910 return (NULL);
911 }
912
913 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
914
915 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
916
917 for (n = vlen; n != 0; n--, ep++) {
918 if (ep->cte_value == value)
919 return (ctf_strptr(fp, ep->cte_name));
920 }
921
922 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
923 return (NULL);
924 }
925
926 /*
927 * Convert the specified enum tag name to the corresponding value, if a
928 * matching name can be found. Otherwise CTF_ERR is returned.
929 */
930 int
ctf_enum_value(ctf_file_t * fp,ctf_id_t type,const char * name,int * valp)931 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
932 {
933 ctf_file_t *ofp = fp;
934 const void *tp;
935 const ctf_enum_t *ep;
936 ssize_t size, increment;
937 uint_t kind, n, vlen;
938
939 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
940 return (CTF_ERR); /* errno is set for us */
941
942 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
943 return (CTF_ERR); /* errno is set for us */
944
945 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
946
947 if (kind != CTF_K_ENUM) {
948 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
949 return (CTF_ERR);
950 }
951
952 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
953
954 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
955
956 for (n = vlen; n != 0; n--, ep++) {
957 if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
958 if (valp != NULL)
959 *valp = ep->cte_value;
960 return (0);
961 }
962 }
963
964 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
965 return (CTF_ERR);
966 }
967
968 /*
969 * Recursively visit the members of any type. This function is used as the
970 * engine for ctf_type_visit, below. We resolve the input type, recursively
971 * invoke ourself for each type member if the type is a struct or union, and
972 * then invoke the callback function on the current type. If any callback
973 * returns non-zero, we abort and percolate the error code back up to the top.
974 */
975 static int
ctf_type_rvisit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg,const char * name,ulong_t offset,int depth)976 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
977 const char *name, ulong_t offset, int depth)
978 {
979 ctf_id_t otype = type;
980 const void *tp;
981 ssize_t size, increment;
982 uint_t kind, n, vlen;
983 int rc;
984
985 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
986 return (CTF_ERR); /* errno is set for us */
987
988 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
989 return (CTF_ERR); /* errno is set for us */
990
991 if ((rc = func(name, otype, offset, depth, arg)) != 0)
992 return (rc);
993
994 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
995
996 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
997 return (0);
998
999 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
1000
1001 const char *mp = (const char *)((uintptr_t)tp + increment);
1002 for (n = vlen; n != 0; n--, mp += increment) {
1003 const char *xname;
1004 ulong_t offset1;
1005 uint_t xtype;
1006
1007 ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset1,
1008 &xname);
1009 if ((rc = ctf_type_rvisit(fp, xtype, func, arg, xname,
1010 offset + offset1, depth + 1)) != 0)
1011 return (rc);
1012 }
1013
1014 return (0);
1015 }
1016
1017 /*
1018 * Recursively visit the members of any type. We pass the name, member
1019 * type, and offset of each member to the specified callback function.
1020 */
1021 int
ctf_type_visit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg)1022 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
1023 {
1024 return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
1025 }
1026