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
23 /*
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27 /*
28 * Copyright 2020 Joyent, Inc.
29 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
30 * Copyright 2025 Oxide Computer Company
31 */
32
33 #include <ctf_impl.h>
34 #include <sys/debug.h>
35
36 ssize_t
ctf_get_ctt_size(const ctf_file_t * fp,const ctf_type_t * tp,ssize_t * sizep,ssize_t * incrementp)37 ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep,
38 ssize_t *incrementp)
39 {
40 ssize_t size, increment;
41
42 if (fp->ctf_version > CTF_VERSION_1 &&
43 tp->ctt_size == CTF_LSIZE_SENT) {
44 size = CTF_TYPE_LSIZE(tp);
45 increment = sizeof (ctf_type_t);
46 } else {
47 size = tp->ctt_size;
48 increment = sizeof (ctf_stype_t);
49 }
50
51 if (sizep)
52 *sizep = size;
53 if (incrementp)
54 *incrementp = increment;
55
56 return (size);
57 }
58
59 void
ctf_set_ctt_size(ctf_type_t * tp,ssize_t size)60 ctf_set_ctt_size(ctf_type_t *tp, ssize_t size)
61 {
62 if (size > CTF_MAX_SIZE) {
63 tp->ctt_size = CTF_LSIZE_SENT;
64 tp->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
65 tp->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
66 } else {
67 tp->ctt_size = (ushort_t)size;
68 }
69 }
70
71 /*
72 * Iterate over the members of a STRUCT or UNION. We pass the name, member
73 * type, and offset of each member to the specified callback function.
74 */
75 int
ctf_member_iter(ctf_file_t * fp,ctf_id_t type,ctf_member_f * func,void * arg)76 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
77 {
78 ctf_file_t *ofp = fp;
79 const ctf_type_t *tp;
80 ssize_t size, increment;
81 uint_t kind, n;
82 int rc;
83
84 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
85 return (CTF_ERR); /* errno is set for us */
86
87 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
88 return (CTF_ERR); /* errno is set for us */
89
90 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
91 kind = LCTF_INFO_KIND(fp, tp->ctt_info);
92
93 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
94 return (ctf_set_errno(ofp, ECTF_NOTSOU));
95
96 if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {
97 const ctf_member_t *mp = (const ctf_member_t *)
98 ((uintptr_t)tp + increment);
99
100 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {
101 const char *name = ctf_strptr(fp, mp->ctm_name);
102 if ((rc = func(name, mp->ctm_type, mp->ctm_offset,
103 arg)) != 0)
104 return (rc);
105 }
106
107 } else {
108 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
109 ((uintptr_t)tp + increment);
110
111 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {
112 const char *name = ctf_strptr(fp, lmp->ctlm_name);
113 if ((rc = func(name, lmp->ctlm_type,
114 (ulong_t)CTF_LMEM_OFFSET(lmp), arg)) != 0)
115 return (rc);
116 }
117 }
118
119 return (0);
120 }
121
122 /*
123 * Iterate over the members of an ENUM. We pass the string name and associated
124 * integer value of each enum element to the specified callback function.
125 */
126 int
ctf_enum_iter(ctf_file_t * fp,ctf_id_t type,ctf_enum_f * func,void * arg)127 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
128 {
129 ctf_file_t *ofp = fp;
130 const ctf_type_t *tp;
131 const ctf_enum_t *ep;
132 ssize_t increment;
133 uint_t n;
134 int rc;
135
136 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
137 return (CTF_ERR); /* errno is set for us */
138
139 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
140 return (CTF_ERR); /* errno is set for us */
141
142 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM)
143 return (ctf_set_errno(ofp, ECTF_NOTENUM));
144
145 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
146
147 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
148
149 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
150 const char *name = ctf_strptr(fp, ep->cte_name);
151 if ((rc = func(name, ep->cte_value, arg)) != 0)
152 return (rc);
153 }
154
155 return (0);
156 }
157
158 /*
159 * Iterate over every type in the given CTF container. If the user doesn't ask
160 * for all types, then we only give them the user visible, aka root, types. We
161 * pass the type ID of each type to the specified callback function.
162 */
163 int
ctf_type_iter(ctf_file_t * fp,boolean_t nonroot,ctf_type_f * func,void * arg)164 ctf_type_iter(ctf_file_t *fp, boolean_t nonroot, ctf_type_f *func, void *arg)
165 {
166 ctf_id_t id, max = fp->ctf_typemax;
167 int rc, child = (fp->ctf_flags & LCTF_CHILD);
168
169 for (id = 1; id <= max; id++) {
170 const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
171 if ((nonroot || CTF_INFO_ISROOT(tp->ctt_info)) &&
172 (rc = func(CTF_INDEX_TO_TYPE(id, child),
173 CTF_INFO_ISROOT(tp->ctt_info), arg)) != 0)
174 return (rc);
175 }
176
177 return (0);
178 }
179
180 /*
181 * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
182 * RESTRICT nodes until we reach a "base" type node. This is useful when
183 * we want to follow a type ID to a node that has members or a size. To guard
184 * against infinite loops, we implement simplified cycle detection and check
185 * each link against itself, the previous node, and the topmost node.
186 */
187 ctf_id_t
ctf_type_resolve(ctf_file_t * fp,ctf_id_t type)188 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
189 {
190 ctf_id_t prev = type, otype = type;
191 ctf_file_t *ofp = fp;
192 const ctf_type_t *tp;
193
194 while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
195 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
196 case CTF_K_TYPEDEF:
197 case CTF_K_VOLATILE:
198 case CTF_K_CONST:
199 case CTF_K_RESTRICT:
200 if (tp->ctt_type == type || tp->ctt_type == otype ||
201 tp->ctt_type == prev) {
202 ctf_dprintf("type %ld cycle detected\n", otype);
203 return (ctf_set_errno(ofp, ECTF_CORRUPT));
204 }
205 prev = type;
206 type = tp->ctt_type;
207 break;
208 default:
209 return (type);
210 }
211 }
212
213 return (CTF_ERR); /* errno is set for us */
214 }
215
216 /*
217 * Format an integer type; if a vname is specified, we need to insert it prior
218 * to any bitfield ":24" suffix. This works out far simpler than figuring it
219 * out from scratch.
220 */
221 static const char *
ctf_format_int(ctf_decl_t * cd,const char * vname,const char * qname,const char * name)222 ctf_format_int(ctf_decl_t *cd, const char *vname, const char *qname,
223 const char *name)
224 {
225 const char *c;
226
227 if (vname == NULL) {
228 if (qname != NULL)
229 ctf_decl_sprintf(cd, "%s`%s", qname, name);
230 else
231 ctf_decl_sprintf(cd, "%s", name);
232 return (NULL);
233 }
234
235 if ((c = strchr(name, ':')) == NULL) {
236 ctf_decl_sprintf(cd, "%s", name);
237 return (vname);
238 }
239
240 /* "unsigned int mybits:23" */
241 ctf_decl_sprintf(cd, "%.*s %s%s", c - name, name, vname, c);
242 return (NULL);
243 }
244
245 static void
ctf_format_func(ctf_file_t * fp,ctf_decl_t * cd,const char * vname,ctf_id_t id,int want_func_args)246 ctf_format_func(ctf_file_t *fp, ctf_decl_t *cd,
247 const char *vname, ctf_id_t id, int want_func_args)
248 {
249 ctf_funcinfo_t fi;
250 /* We'll presume zone_create() is a bad example. */
251 ctf_id_t args[20];
252
253 ctf_decl_sprintf(cd, "%s(", vname == NULL ? "" : vname);
254
255 if (!want_func_args)
256 goto out;
257
258 if (ctf_func_info_by_id(fp, id, &fi) != 0)
259 goto out;
260
261 if (fi.ctc_argc > ARRAY_SIZE(args))
262 fi.ctc_argc = ARRAY_SIZE(args);
263
264 if (fi.ctc_argc == 0) {
265 ctf_decl_sprintf(cd, "void");
266 goto out;
267 }
268
269 if (ctf_func_args_by_id(fp, id, fi.ctc_argc, args) != 0)
270 goto out;
271
272 for (size_t i = 0; i < fi.ctc_argc; i++) {
273 char aname[512];
274
275 if (ctf_type_name(fp, args[i], aname, sizeof (aname)) == NULL)
276 (void) strlcpy(aname, "unknown_t", sizeof (aname));
277
278 ctf_decl_sprintf(cd, "%s%s", aname,
279 i + 1 == fi.ctc_argc ? "" : ", ");
280 }
281
282 if (fi.ctc_flags & CTF_FUNC_VARARG)
283 ctf_decl_sprintf(cd, "%s...", fi.ctc_argc == 0 ? "" : ", ");
284
285 out:
286 ctf_decl_sprintf(cd, ")");
287 }
288
289 /*
290 * Lookup the given type ID and print a string name for it into buf. Return the
291 * actual number of bytes (not including \0) needed to format the name.
292 *
293 * "vname" is an optional variable name or similar, so array suffix formatting,
294 * bitfields, and functions are C-correct. (This is not perfect, as can be seen
295 * in kiconv_ops_t.)
296 */
297 static ssize_t
ctf_type_qlname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * vname,const char * qname)298 ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
299 const char *vname, const char *qname)
300 {
301 int want_func_args = (vname != NULL);
302 ctf_decl_t cd;
303 ctf_decl_node_t *cdp;
304 ctf_decl_prec_t prec, lp, rp;
305 int ptr, arr;
306 uint_t k;
307
308 if (fp == NULL && type == CTF_ERR)
309 return (-1); /* simplify caller code by permitting CTF_ERR */
310
311 ctf_decl_init(&cd, buf, len);
312 ctf_decl_push(&cd, fp, type);
313
314 if (cd.cd_err != 0) {
315 ctf_decl_fini(&cd);
316 return (ctf_set_errno(fp, cd.cd_err));
317 }
318
319 /*
320 * If the type graph's order conflicts with lexical precedence order
321 * for pointers or arrays, then we need to surround the declarations at
322 * the corresponding lexical precedence with parentheses. This can
323 * result in either a parenthesized pointer (*) as in int (*)() or
324 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
325 */
326 ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
327 arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
328
329 rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
330 lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
331
332 k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
333
334 for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
335 for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
336 cdp != NULL; cdp = ctf_list_next(cdp)) {
337
338 ctf_file_t *rfp = fp;
339 const ctf_type_t *tp =
340 ctf_lookup_by_id(&rfp, cdp->cd_type);
341 const char *name = ctf_strptr(rfp, tp->ctt_name);
342
343 if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
344 ctf_decl_sprintf(&cd, " ");
345
346 if (lp == prec) {
347 ctf_decl_sprintf(&cd, "(");
348 lp = -1;
349 }
350
351 switch (cdp->cd_kind) {
352 case CTF_K_INTEGER:
353 vname = ctf_format_int(&cd, vname, qname, name);
354 break;
355 case CTF_K_FLOAT:
356 case CTF_K_TYPEDEF:
357 if (qname != NULL)
358 ctf_decl_sprintf(&cd, "%s`", qname);
359 ctf_decl_sprintf(&cd, "%s", name);
360 break;
361 case CTF_K_POINTER:
362 ctf_decl_sprintf(&cd, "*");
363 break;
364 case CTF_K_ARRAY:
365 ctf_decl_sprintf(&cd, "%s[%u]",
366 vname != NULL ? vname : "", cdp->cd_n);
367 vname = NULL;
368 break;
369 case CTF_K_FUNCTION:
370 ctf_format_func(fp, &cd, vname,
371 cdp->cd_type, want_func_args);
372 vname = NULL;
373 break;
374 case CTF_K_FORWARD:
375 switch (tp->ctt_type) {
376 case CTF_K_UNION:
377 ctf_decl_sprintf(&cd, "union ");
378 break;
379 case CTF_K_ENUM:
380 ctf_decl_sprintf(&cd, "enum ");
381 break;
382 case CTF_K_STRUCT:
383 default:
384 ctf_decl_sprintf(&cd, "struct ");
385 break;
386 }
387 if (qname != NULL)
388 ctf_decl_sprintf(&cd, "%s`", qname);
389 ctf_decl_sprintf(&cd, "%s", name);
390 break;
391 case CTF_K_STRUCT:
392 ctf_decl_sprintf(&cd, "struct ");
393 if (qname != NULL)
394 ctf_decl_sprintf(&cd, "%s`", qname);
395 ctf_decl_sprintf(&cd, "%s", name);
396 break;
397 case CTF_K_UNION:
398 ctf_decl_sprintf(&cd, "union ");
399 if (qname != NULL)
400 ctf_decl_sprintf(&cd, "%s`", qname);
401 ctf_decl_sprintf(&cd, "%s", name);
402 break;
403 case CTF_K_ENUM:
404 ctf_decl_sprintf(&cd, "enum ");
405 if (qname != NULL)
406 ctf_decl_sprintf(&cd, "%s`", qname);
407 ctf_decl_sprintf(&cd, "%s", name);
408 break;
409 case CTF_K_VOLATILE:
410 ctf_decl_sprintf(&cd, "volatile");
411 break;
412 case CTF_K_CONST:
413 ctf_decl_sprintf(&cd, "const");
414 break;
415 case CTF_K_RESTRICT:
416 ctf_decl_sprintf(&cd, "restrict");
417 break;
418 }
419
420 k = cdp->cd_kind;
421 }
422
423 if (rp == prec) {
424 /*
425 * Peek ahead: if we're going to hit a function,
426 * we want to insert its name now before this closing
427 * bracket.
428 */
429 if (vname != NULL && prec < CTF_PREC_FUNCTION) {
430 cdp = ctf_list_next(
431 &cd.cd_nodes[CTF_PREC_FUNCTION]);
432
433 if (cdp != NULL) {
434 ctf_decl_sprintf(&cd, "%s", vname);
435 vname = NULL;
436 }
437 }
438
439 ctf_decl_sprintf(&cd, ")");
440 }
441 }
442
443 if (vname != NULL)
444 ctf_decl_sprintf(&cd, " %s", vname);
445
446 if (cd.cd_len >= len)
447 (void) ctf_set_errno(fp, ECTF_NAMELEN);
448
449 ctf_decl_fini(&cd);
450 return (cd.cd_len);
451 }
452
453 ssize_t
ctf_type_lname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)454 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
455 {
456 return (ctf_type_qlname(fp, type, buf, len, NULL, NULL));
457 }
458
459 /*
460 * Lookup the given type ID and print a string name for it into buf. If buf
461 * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
462 */
463 char *
ctf_type_name(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)464 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
465 {
466 ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL, NULL);
467 return (rv >= 0 && rv < len ? buf : NULL);
468 }
469
470 char *
ctf_type_qname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * qname)471 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
472 const char *qname)
473 {
474 ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL, qname);
475 return (rv >= 0 && rv < len ? buf : NULL);
476 }
477
478 char *
ctf_type_cname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len,const char * cname)479 ctf_type_cname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
480 const char *cname)
481 {
482 ssize_t rv = ctf_type_qlname(fp, type, buf, len, cname, NULL);
483 return (rv >= 0 && rv < len ? buf : NULL);
484 }
485
486 /*
487 * Resolve the type down to a base type node, and then return the size
488 * of the type storage in bytes.
489 */
490 ssize_t
ctf_type_size(ctf_file_t * fp,ctf_id_t type)491 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
492 {
493 const ctf_type_t *tp;
494 ssize_t size;
495 ctf_arinfo_t ar;
496
497 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
498 return (-1); /* errno is set for us */
499
500 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
501 return (-1); /* errno is set for us */
502
503 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
504 case CTF_K_POINTER:
505 return (fp->ctf_dmodel->ctd_pointer);
506
507 case CTF_K_FUNCTION:
508 return (0); /* function size is only known by symtab */
509
510 case CTF_K_FORWARD:
511 return (0);
512
513 case CTF_K_ENUM:
514 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
515
516 case CTF_K_ARRAY:
517 /*
518 * Array size is not directly returned by stabs data. Instead,
519 * it defines the element type and requires the user to perform
520 * the multiplication. If ctf_get_ctt_size() returns zero, the
521 * current version of ctfconvert does not compute member sizes
522 * and we compute the size here on its behalf.
523 */
524 if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
525 return (size);
526
527 if (ctf_array_info(fp, type, &ar) == CTF_ERR ||
528 (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR)
529 return (-1); /* errno is set for us */
530
531 return (size * ar.ctr_nelems);
532 case CTF_K_STRUCT:
533 case CTF_K_UNION:
534 /*
535 * If we have a zero size, we may be in the process of adding a
536 * structure or union but having not called ctf_update() to deal
537 * with the circular dependencies in such structures and unions.
538 * To handle that case, if we get a size of zero from the ctt,
539 * we look up the dtdef and use its size instead.
540 */
541 size = ctf_get_ctt_size(fp, tp, NULL, NULL);
542 if (size == 0) {
543 ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
544 if (dtd != NULL)
545 return (dtd->dtd_data.ctt_size);
546 }
547 return (size);
548 default:
549 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
550 }
551 }
552
553 /*
554 * Resolve the type down to a base type node, and then return the alignment
555 * needed for the type storage in bytes.
556 */
557 ssize_t
ctf_type_align(ctf_file_t * fp,ctf_id_t type)558 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
559 {
560 const ctf_type_t *tp;
561 ctf_arinfo_t r;
562
563 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
564 return (-1); /* errno is set for us */
565
566 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
567 return (-1); /* errno is set for us */
568
569 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
570 case CTF_K_POINTER:
571 case CTF_K_FUNCTION:
572 return (fp->ctf_dmodel->ctd_pointer);
573
574 case CTF_K_ARRAY:
575 if (ctf_array_info(fp, type, &r) == CTF_ERR)
576 return (-1); /* errno is set for us */
577 return (ctf_type_align(fp, r.ctr_contents));
578
579 case CTF_K_STRUCT:
580 case CTF_K_UNION: {
581 uint_t n = LCTF_INFO_VLEN(fp, tp->ctt_info);
582 ssize_t size, increment;
583 size_t align = 0;
584 const void *vmp;
585
586 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
587 vmp = (uchar_t *)tp + increment;
588
589 if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_STRUCT)
590 n = MIN(n, 1); /* only use first member for structs */
591
592 if (fp->ctf_version == CTF_VERSION_1 ||
593 size < CTF_LSTRUCT_THRESH) {
594 const ctf_member_t *mp = vmp;
595 for (; n != 0; n--, mp++) {
596 ssize_t am = ctf_type_align(fp, mp->ctm_type);
597 align = MAX(align, am);
598 }
599 } else {
600 const ctf_lmember_t *lmp = vmp;
601 for (; n != 0; n--, lmp++) {
602 ssize_t am = ctf_type_align(fp, lmp->ctlm_type);
603 align = MAX(align, am);
604 }
605 }
606
607 return (align);
608 }
609
610 case CTF_K_ENUM:
611 default:
612 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
613 }
614 }
615
616 /*
617 * Return the kind (CTF_K_* constant) for the specified type ID.
618 */
619 int
ctf_type_kind(ctf_file_t * fp,ctf_id_t type)620 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
621 {
622 const ctf_type_t *tp;
623
624 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
625 return (CTF_ERR); /* errno is set for us */
626
627 return (LCTF_INFO_KIND(fp, tp->ctt_info));
628 }
629
630 /*
631 * If the type is one that directly references another type (such as POINTER),
632 * then return the ID of the type to which it refers.
633 */
634 ctf_id_t
ctf_type_reference(ctf_file_t * fp,ctf_id_t type)635 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
636 {
637 ctf_file_t *ofp = fp;
638 const ctf_type_t *tp;
639
640 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
641 return (CTF_ERR); /* errno is set for us */
642
643 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
644 case CTF_K_POINTER:
645 case CTF_K_TYPEDEF:
646 case CTF_K_VOLATILE:
647 case CTF_K_CONST:
648 case CTF_K_RESTRICT:
649 return (tp->ctt_type);
650 default:
651 return (ctf_set_errno(ofp, ECTF_NOTREF));
652 }
653 }
654
655 /*
656 * Find a pointer to type by looking in fp->ctf_ptrtab. If we can't find a
657 * pointer to the given type, see if we can compute a pointer to the type
658 * resulting from resolving the type down to its base type and use that
659 * instead. This helps with cases where the CTF data includes "struct foo *"
660 * but not "foo_t *" and the user accesses "foo_t *" in the debugger.
661 */
662 ctf_id_t
ctf_type_pointer(ctf_file_t * fp,ctf_id_t type)663 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
664 {
665 ctf_file_t *ofp = fp;
666 ctf_id_t ntype;
667
668 if (ctf_lookup_by_id(&fp, type) == NULL)
669 return (CTF_ERR); /* errno is set for us */
670
671 if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
672 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
673
674 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
675 return (ctf_set_errno(ofp, ECTF_NOTYPE));
676
677 if (ctf_lookup_by_id(&fp, type) == NULL)
678 return (ctf_set_errno(ofp, ECTF_NOTYPE));
679
680 if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
681 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
682
683 return (ctf_set_errno(ofp, ECTF_NOTYPE));
684 }
685
686 /*
687 * Return the encoding for the specified INTEGER or FLOAT.
688 */
689 int
ctf_type_encoding(ctf_file_t * fp,ctf_id_t type,ctf_encoding_t * ep)690 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
691 {
692 ctf_file_t *ofp = fp;
693 const ctf_type_t *tp;
694 ssize_t increment;
695 uint_t data;
696
697 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
698 return (CTF_ERR); /* errno is set for us */
699
700 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
701
702 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
703 case CTF_K_INTEGER:
704 data = *(const uint_t *)((uintptr_t)tp + increment);
705 ep->cte_format = CTF_INT_ENCODING(data);
706 ep->cte_offset = CTF_INT_OFFSET(data);
707 ep->cte_bits = CTF_INT_BITS(data);
708 break;
709 case CTF_K_FLOAT:
710 data = *(const uint_t *)((uintptr_t)tp + increment);
711 ep->cte_format = CTF_FP_ENCODING(data);
712 ep->cte_offset = CTF_FP_OFFSET(data);
713 ep->cte_bits = CTF_FP_BITS(data);
714 break;
715 default:
716 return (ctf_set_errno(ofp, ECTF_NOTINTFP));
717 }
718
719 return (0);
720 }
721
722 int
ctf_type_cmp(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)723 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
724 {
725 int rval;
726
727 if (ltype < rtype)
728 rval = -1;
729 else if (ltype > rtype)
730 rval = 1;
731 else
732 rval = 0;
733
734 if (lfp == rfp)
735 return (rval);
736
737 if (CTF_TYPE_ISPARENT(ltype) && lfp->ctf_parent != NULL)
738 lfp = lfp->ctf_parent;
739
740 if (CTF_TYPE_ISPARENT(rtype) && rfp->ctf_parent != NULL)
741 rfp = rfp->ctf_parent;
742
743 if (lfp < rfp)
744 return (-1);
745
746 if (lfp > rfp)
747 return (1);
748
749 return (rval);
750 }
751
752 /*
753 * Return a boolean value indicating if two types are compatible integers or
754 * floating-pointer values. This function returns true if the two types are
755 * the same, or if they have the same ASCII name and encoding properties.
756 * This function could be extended to test for compatibility for other kinds.
757 */
758 int
ctf_type_compat(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)759 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
760 ctf_file_t *rfp, ctf_id_t rtype)
761 {
762 const ctf_type_t *ltp, *rtp;
763 ctf_encoding_t le, re;
764 ctf_arinfo_t la, ra;
765 uint_t lkind, rkind;
766
767 if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
768 return (1);
769
770 ltype = ctf_type_resolve(lfp, ltype);
771 lkind = ctf_type_kind(lfp, ltype);
772
773 rtype = ctf_type_resolve(rfp, rtype);
774 rkind = ctf_type_kind(rfp, rtype);
775
776 if (lkind != rkind ||
777 (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
778 (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
779 strcmp(ctf_strptr(lfp, ltp->ctt_name),
780 ctf_strptr(rfp, rtp->ctt_name)) != 0)
781 return (0);
782
783 switch (lkind) {
784 case CTF_K_INTEGER:
785 case CTF_K_FLOAT:
786 return (ctf_type_encoding(lfp, ltype, &le) == 0 &&
787 ctf_type_encoding(rfp, rtype, &re) == 0 &&
788 bcmp(&le, &re, sizeof (ctf_encoding_t)) == 0);
789 case CTF_K_POINTER:
790 return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
791 rfp, ctf_type_reference(rfp, rtype)));
792 case CTF_K_ARRAY:
793 return (ctf_array_info(lfp, ltype, &la) == 0 &&
794 ctf_array_info(rfp, rtype, &ra) == 0 &&
795 la.ctr_nelems == ra.ctr_nelems && ctf_type_compat(
796 lfp, la.ctr_contents, rfp, ra.ctr_contents) &&
797 ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index));
798 case CTF_K_STRUCT:
799 case CTF_K_UNION:
800 return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
801 case CTF_K_ENUM:
802 case CTF_K_FORWARD:
803 return (1); /* no other checks required for these type kinds */
804 default:
805 return (0); /* should not get here since we did a resolve */
806 }
807 }
808
809 typedef struct {
810 ctf_file_t *cms_fp;
811 const ctf_type_t *cms_tp;
812 ulong_t cms_curoff;
813 } ctf_member_stack_t;
814
815 /*
816 * Determine whether or not we should push this frame on. If we're at our depth,
817 * then that's it. In particular for us to look at this we need to:
818 *
819 * 1) Have no name.
820 * 2) Be a struct or union (implicitly that means we can look this up).
821 * 3) Not exceed our internal depth.
822 */
823 static void
ctf_member_info_push(ctf_member_stack_t * stack,size_t * depthp,size_t max,const ctf_member_stack_t * cur,ushort_t mtype,const char * mname,ulong_t moff)824 ctf_member_info_push(ctf_member_stack_t *stack, size_t *depthp, size_t max,
825 const ctf_member_stack_t *cur, ushort_t mtype, const char *mname,
826 ulong_t moff)
827 {
828 uint_t kind;
829 ctf_member_stack_t *cms;
830
831 if (*depthp == max)
832 return;
833
834 if (*mname != '\0')
835 return;
836
837 cms = &stack[*depthp];
838 cms->cms_fp = cur->cms_fp;
839 cms->cms_tp = ctf_lookup_by_id(&cms->cms_fp, mtype);
840 if (cms->cms_tp == NULL)
841 return;
842 kind = LCTF_INFO_KIND(cms->cms_fp, cms->cms_tp->ctt_info);
843 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
844 return;
845 cms->cms_curoff = cur->cms_curoff + moff;
846 *depthp = *depthp + 1;
847 }
848
849 /*
850 * Return the type and offset for a given member of a STRUCT or UNION. C11
851 * officially added anonymous structs and unions. These are members whose name
852 * is the empty string. When looking for a member, we will search anonymous
853 * structures and unions it. This can nest to an arbitrary depth; however, we
854 * use a fixed bound to limit our overall stack usage. This will cause us to go
855 * through and visit all of our current members before considering any anonymous
856 * entries. Note, this is okay because there are no duplicate member names
857 * allowed.
858 */
859 int
ctf_member_info(ctf_file_t * ifp,ctf_id_t type,const char * name,ctf_membinfo_t * mip)860 ctf_member_info(ctf_file_t *ifp, ctf_id_t type, const char *name,
861 ctf_membinfo_t *mip)
862 {
863 uint_t kind;
864 ctf_member_stack_t stack[128];
865 size_t depth = 0;
866
867 /*
868 * We only ever resolve the top-level type while searching.
869 */
870 if ((type = ctf_type_resolve(ifp, type)) == CTF_ERR)
871 return (CTF_ERR); /* errno is set for us */
872
873 stack[depth].cms_fp = ifp;
874 stack[depth].cms_curoff = 0;
875 stack[depth].cms_tp = ctf_lookup_by_id(&stack[depth].cms_fp, type);
876 if (stack[depth].cms_tp == NULL)
877 return (CTF_ERR); /* errno is set for us */
878
879 kind = LCTF_INFO_KIND(stack[depth].cms_fp,
880 stack[depth].cms_tp->ctt_info);
881
882 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
883 return (ctf_set_errno(ifp, ECTF_NOTSOU));
884
885 depth++;
886 while (depth != 0) {
887 ssize_t size, increment;
888 ctf_member_stack_t cms;
889
890 depth--;
891 cms = stack[depth];
892
893 (void) ctf_get_ctt_size(cms.cms_fp, cms.cms_tp, &size,
894 &increment);
895
896 if (cms.cms_fp->ctf_version == CTF_VERSION_1 ||
897 size < CTF_LSTRUCT_THRESH) {
898 const ctf_member_t *mp = (const ctf_member_t *)
899 ((uintptr_t)cms.cms_tp + increment);
900
901 for (uint_t n = LCTF_INFO_VLEN(cms.cms_fp,
902 cms.cms_tp->ctt_info); n != 0; n--, mp++) {
903 const char *mname = ctf_strptr(cms.cms_fp,
904 mp->ctm_name);
905
906 if (strcmp(mname, name) == 0) {
907 mip->ctm_type = mp->ctm_type;
908 mip->ctm_offset = mp->ctm_offset +
909 cms.cms_curoff;
910 return (0);
911 }
912
913 ctf_member_info_push(stack, &depth,
914 ARRAY_SIZE(stack), &cms, mp->ctm_type,
915 mname, mp->ctm_offset);
916 }
917 } else {
918 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
919 ((uintptr_t)cms.cms_tp + increment);
920
921 for (uint_t n = LCTF_INFO_VLEN(cms.cms_fp,
922 cms.cms_tp->ctt_info); n != 0; n--, lmp++) {
923 const char *mname = ctf_strptr(cms.cms_fp,
924 lmp->ctlm_name);
925 ulong_t off = (ulong_t)CTF_LMEM_OFFSET(lmp);
926 if (strcmp(mname, name) == 0) {
927 mip->ctm_type = lmp->ctlm_type;
928 mip->ctm_offset = cms.cms_curoff + off;
929 return (0);
930 }
931
932 ctf_member_info_push(stack, &depth,
933 ARRAY_SIZE(stack), &cms, lmp->ctlm_type,
934 mname, off);
935 }
936 }
937
938 }
939
940 return (ctf_set_errno(ifp, ECTF_NOMEMBNAM));
941 }
942
943 /*
944 * Return the array type, index, and size information for the specified ARRAY.
945 */
946 int
ctf_array_info(ctf_file_t * fp,ctf_id_t type,ctf_arinfo_t * arp)947 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
948 {
949 ctf_file_t *ofp = fp;
950 const ctf_type_t *tp;
951 const ctf_array_t *ap;
952 ssize_t increment;
953
954 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
955 return (CTF_ERR); /* errno is set for us */
956
957 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ARRAY)
958 return (ctf_set_errno(ofp, ECTF_NOTARRAY));
959
960 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
961
962 ap = (const ctf_array_t *)((uintptr_t)tp + increment);
963 arp->ctr_contents = ap->cta_contents;
964 arp->ctr_index = ap->cta_index;
965 arp->ctr_nelems = ap->cta_nelems;
966
967 return (0);
968 }
969
970 /*
971 * Convert the specified value to the corresponding enum member name, if a
972 * matching name can be found. Otherwise NULL is returned.
973 */
974 const char *
ctf_enum_name(ctf_file_t * fp,ctf_id_t type,int value)975 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
976 {
977 ctf_file_t *ofp = fp;
978 const ctf_type_t *tp;
979 const ctf_enum_t *ep;
980 ssize_t increment;
981 uint_t n;
982
983 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
984 return (NULL); /* errno is set for us */
985
986 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
987 return (NULL); /* errno is set for us */
988
989 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
990 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
991 return (NULL);
992 }
993
994 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
995
996 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
997
998 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
999 if (ep->cte_value == value)
1000 return (ctf_strptr(fp, ep->cte_name));
1001 }
1002
1003 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
1004 return (NULL);
1005 }
1006
1007 /*
1008 * Convert the specified enum tag name to the corresponding value, if a
1009 * matching name can be found. Otherwise CTF_ERR is returned.
1010 */
1011 int
ctf_enum_value(ctf_file_t * fp,ctf_id_t type,const char * name,int * valp)1012 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
1013 {
1014 ctf_file_t *ofp = fp;
1015 const ctf_type_t *tp;
1016 const ctf_enum_t *ep;
1017 ssize_t size, increment;
1018 uint_t n;
1019
1020 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
1021 return (CTF_ERR); /* errno is set for us */
1022
1023 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
1024 return (CTF_ERR); /* errno is set for us */
1025
1026 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
1027 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
1028 return (CTF_ERR);
1029 }
1030
1031 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
1032
1033 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
1034
1035 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
1036 if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
1037 if (valp != NULL)
1038 *valp = ep->cte_value;
1039 return (0);
1040 }
1041 }
1042
1043 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
1044 return (CTF_ERR);
1045 }
1046
1047 /*
1048 * Recursively visit the members of any type. This function is used as the
1049 * engine for ctf_type_visit, below. We resolve the input type, recursively
1050 * invoke ourself for each type member if the type is a struct or union, and
1051 * then invoke the callback function on the current type. If any callback
1052 * returns non-zero, we abort and percolate the error code back up to the top.
1053 */
1054 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)1055 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
1056 const char *name, ulong_t offset, int depth)
1057 {
1058 ctf_id_t otype = type;
1059 const ctf_type_t *tp;
1060 ssize_t size, increment;
1061 uint_t kind, n;
1062 int rc;
1063
1064 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
1065 return (CTF_ERR); /* errno is set for us */
1066
1067 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
1068 return (CTF_ERR); /* errno is set for us */
1069
1070 if ((rc = func(name, otype, offset, depth, arg)) != 0)
1071 return (rc);
1072
1073 kind = LCTF_INFO_KIND(fp, tp->ctt_info);
1074
1075 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
1076 return (0);
1077
1078 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
1079
1080 if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {
1081 const ctf_member_t *mp = (const ctf_member_t *)
1082 ((uintptr_t)tp + increment);
1083
1084 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {
1085 if ((rc = ctf_type_rvisit(fp, mp->ctm_type,
1086 func, arg, ctf_strptr(fp, mp->ctm_name),
1087 offset + mp->ctm_offset, depth + 1)) != 0)
1088 return (rc);
1089 }
1090
1091 } else {
1092 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
1093 ((uintptr_t)tp + increment);
1094
1095 for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {
1096 if ((rc = ctf_type_rvisit(fp, lmp->ctlm_type,
1097 func, arg, ctf_strptr(fp, lmp->ctlm_name),
1098 offset + (ulong_t)CTF_LMEM_OFFSET(lmp),
1099 depth + 1)) != 0)
1100 return (rc);
1101 }
1102 }
1103
1104 return (0);
1105 }
1106
1107 /*
1108 * Recursively visit the members of any type. We pass the name, member
1109 * type, and offset of each member to the specified callback function.
1110 */
1111 int
ctf_type_visit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg)1112 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
1113 {
1114 return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
1115 }
1116
1117 int
ctf_func_info_by_id(ctf_file_t * fp,ctf_id_t type,ctf_funcinfo_t * fip)1118 ctf_func_info_by_id(ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
1119 {
1120 ctf_file_t *ofp = fp;
1121 const ctf_type_t *tp;
1122 const ushort_t *dp;
1123 int nargs;
1124 ssize_t increment;
1125
1126 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
1127 return (CTF_ERR); /* errno is set for us */
1128
1129 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION)
1130 return (ctf_set_errno(ofp, ECTF_NOTFUNC));
1131
1132 fip->ctc_return = tp->ctt_type;
1133 nargs = LCTF_INFO_VLEN(fp, tp->ctt_info);
1134 fip->ctc_argc = nargs;
1135 fip->ctc_flags = 0;
1136
1137 /* dp should now point to the first argument */
1138 if (nargs != 0) {
1139 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
1140 dp = (ushort_t *)((uintptr_t)fp->ctf_buf +
1141 fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] + increment);
1142 if (dp[nargs - 1] == 0) {
1143 fip->ctc_flags |= CTF_FUNC_VARARG;
1144 fip->ctc_argc--;
1145 }
1146 }
1147
1148 return (0);
1149 }
1150
1151 int
ctf_func_args_by_id(ctf_file_t * fp,ctf_id_t type,uint_t argc,ctf_id_t * argv)1152 ctf_func_args_by_id(ctf_file_t *fp, ctf_id_t type, uint_t argc, ctf_id_t *argv)
1153 {
1154 ctf_file_t *ofp = fp;
1155 const ctf_type_t *tp;
1156 const ushort_t *dp;
1157 int nargs;
1158 ssize_t increment;
1159
1160 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
1161 return (CTF_ERR); /* errno is set for us */
1162
1163 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_FUNCTION)
1164 return (ctf_set_errno(ofp, ECTF_NOTFUNC));
1165
1166 nargs = LCTF_INFO_VLEN(fp, tp->ctt_info);
1167 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
1168 dp = (ushort_t *)((uintptr_t)fp->ctf_buf +
1169 fp->ctf_txlate[CTF_TYPE_TO_INDEX(type)] +
1170 increment);
1171 if (nargs != 0 && dp[nargs - 1] == 0)
1172 nargs--;
1173
1174 for (nargs = MIN(argc, nargs); nargs != 0; nargs--)
1175 *argv++ = *dp++;
1176
1177 return (0);
1178 }
1179
1180 int
ctf_object_iter(ctf_file_t * fp,ctf_object_f * func,void * arg)1181 ctf_object_iter(ctf_file_t *fp, ctf_object_f *func, void *arg)
1182 {
1183 int i, ret;
1184 ctf_id_t id;
1185 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1186 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1187
1188 if (fp->ctf_symtab.cts_data == NULL)
1189 return (ctf_set_errno(fp, ECTF_NOSYMTAB));
1190
1191 for (i = 0; i < fp->ctf_nsyms; i++) {
1192 char *name;
1193 if (fp->ctf_sxlate[i] == -1u)
1194 continue;
1195 id = *(ushort_t *)((uintptr_t)fp->ctf_buf +
1196 fp->ctf_sxlate[i]);
1197
1198 /*
1199 * Validate whether or not we're looking at a data object as
1200 * oposed to a function.
1201 */
1202 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1203 const Elf32_Sym *symp = (Elf32_Sym *)symbase + i;
1204 if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT)
1205 continue;
1206 if (fp->ctf_strtab.cts_data != NULL &&
1207 symp->st_name != 0)
1208 name = (char *)(strbase + symp->st_name);
1209 else
1210 name = NULL;
1211 } else {
1212 const Elf64_Sym *symp = (Elf64_Sym *)symbase + i;
1213 if (ELF64_ST_TYPE(symp->st_info) != STT_OBJECT)
1214 continue;
1215 if (fp->ctf_strtab.cts_data != NULL &&
1216 symp->st_name != 0)
1217 name = (char *)(strbase + symp->st_name);
1218 else
1219 name = NULL;
1220 }
1221
1222 if ((ret = func(name, id, i, arg)) != 0)
1223 return (ret);
1224 }
1225
1226 return (0);
1227 }
1228
1229 int
ctf_function_iter(ctf_file_t * fp,ctf_function_f * func,void * arg)1230 ctf_function_iter(ctf_file_t *fp, ctf_function_f *func, void *arg)
1231 {
1232 int i, ret;
1233 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1234 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1235
1236 if (fp->ctf_symtab.cts_data == NULL)
1237 return (ctf_set_errno(fp, ECTF_NOSYMTAB));
1238
1239 for (i = 0; i < fp->ctf_nsyms; i++) {
1240 char *name;
1241 ushort_t info, *dp;
1242 ctf_funcinfo_t fi;
1243 if (fp->ctf_sxlate[i] == -1u)
1244 continue;
1245
1246 dp = (ushort_t *)((uintptr_t)fp->ctf_buf +
1247 fp->ctf_sxlate[i]);
1248 info = *dp;
1249 if (info == 0)
1250 continue;
1251
1252 /*
1253 * This may be a function or it may be a data object. We have to
1254 * consult the symbol table to be certain. Functions are encoded
1255 * with their info, data objects with their actual type.
1256 */
1257 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1258 const Elf32_Sym *symp = (Elf32_Sym *)symbase + i;
1259 if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC)
1260 continue;
1261 if (fp->ctf_strtab.cts_data != NULL)
1262 name = (char *)(strbase + symp->st_name);
1263 else
1264 name = NULL;
1265 } else {
1266 const Elf64_Sym *symp = (Elf64_Sym *)symbase + i;
1267 if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC)
1268 continue;
1269 if (fp->ctf_strtab.cts_data != NULL)
1270 name = (char *)(strbase + symp->st_name);
1271 else
1272 name = NULL;
1273 }
1274
1275 if (LCTF_INFO_KIND(fp, info) != CTF_K_FUNCTION)
1276 continue;
1277 dp++;
1278 fi.ctc_return = *dp;
1279 dp++;
1280 fi.ctc_argc = LCTF_INFO_VLEN(fp, info);
1281 fi.ctc_flags = 0;
1282
1283 if (fi.ctc_argc != 0 && dp[fi.ctc_argc - 1] == 0) {
1284 fi.ctc_flags |= CTF_FUNC_VARARG;
1285 fi.ctc_argc--;
1286 }
1287
1288 if ((ret = func(name, i, &fi, arg)) != 0)
1289 return (ret);
1290
1291 }
1292
1293 return (0);
1294 }
1295
1296 char *
ctf_symbol_name(ctf_file_t * fp,ulong_t idx,char * buf,size_t len)1297 ctf_symbol_name(ctf_file_t *fp, ulong_t idx, char *buf, size_t len)
1298 {
1299 const char *name;
1300 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1301 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1302
1303 if (fp->ctf_symtab.cts_data == NULL) {
1304 (void) ctf_set_errno(fp, ECTF_NOSYMTAB);
1305 return (NULL);
1306 }
1307
1308 if (fp->ctf_strtab.cts_data == NULL) {
1309 (void) ctf_set_errno(fp, ECTF_STRTAB);
1310 return (NULL);
1311 }
1312
1313 if (idx > fp->ctf_nsyms) {
1314 (void) ctf_set_errno(fp, ECTF_NOTDATA);
1315 return (NULL);
1316 }
1317
1318 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1319 const Elf32_Sym *symp = (Elf32_Sym *)symbase + idx;
1320 if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT &&
1321 ELF32_ST_TYPE(symp->st_info) != STT_FUNC) {
1322 (void) ctf_set_errno(fp, ECTF_NOTDATA);
1323 return (NULL);
1324 }
1325 if (symp->st_name == 0) {
1326 (void) ctf_set_errno(fp, ENOENT);
1327 return (NULL);
1328 }
1329 name = (const char *)(strbase + symp->st_name);
1330 } else {
1331 const Elf64_Sym *symp = (Elf64_Sym *)symbase + idx;
1332 if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC &&
1333 ELF64_ST_TYPE(symp->st_info) != STT_OBJECT) {
1334 (void) ctf_set_errno(fp, ECTF_NOTDATA);
1335 return (NULL);
1336 }
1337 if (symp->st_name == 0) {
1338 (void) ctf_set_errno(fp, ENOENT);
1339 return (NULL);
1340 }
1341 name = (const char *)(strbase + symp->st_name);
1342 }
1343
1344 (void) strlcpy(buf, name, len);
1345
1346 return (buf);
1347 }
1348
1349 int
ctf_string_iter(ctf_file_t * fp,ctf_string_f * func,void * arg)1350 ctf_string_iter(ctf_file_t *fp, ctf_string_f *func, void *arg)
1351 {
1352 int rc;
1353 const char *strp = fp->ctf_str[CTF_STRTAB_0].cts_strs;
1354 size_t strl = fp->ctf_str[CTF_STRTAB_0].cts_len;
1355
1356 while (strl > 0) {
1357 size_t len;
1358
1359 if ((rc = func(strp, arg)) != 0)
1360 return (rc);
1361
1362 len = strlen(strp) + 1;
1363 strl -= len;
1364 strp += len;
1365 }
1366
1367 return (0);
1368 }
1369
1370 /*
1371 * fp isn't strictly necessary at the moment. However, if we ever rev the file
1372 * format, the valid values for kind will change.
1373 */
1374 const char *
ctf_kind_name(ctf_file_t * fp,int kind)1375 ctf_kind_name(ctf_file_t *fp, int kind)
1376 {
1377 switch (kind) {
1378 case CTF_K_INTEGER:
1379 return ("integer");
1380 case CTF_K_FLOAT:
1381 return ("float");
1382 case CTF_K_POINTER:
1383 return ("pointer");
1384 case CTF_K_ARRAY:
1385 return ("array");
1386 case CTF_K_FUNCTION:
1387 return ("function");
1388 case CTF_K_STRUCT:
1389 return ("struct");
1390 case CTF_K_UNION:
1391 return ("union");
1392 case CTF_K_ENUM:
1393 return ("enum");
1394 case CTF_K_FORWARD:
1395 return ("forward");
1396 case CTF_K_TYPEDEF:
1397 return ("typedef");
1398 case CTF_K_VOLATILE:
1399 return ("volatile");
1400 case CTF_K_CONST:
1401 return ("const");
1402 case CTF_K_RESTRICT:
1403 return ("restrict");
1404 case CTF_K_UNKNOWN:
1405 default:
1406 return ("unknown");
1407 }
1408 }
1409
1410 ctf_id_t
ctf_max_id(ctf_file_t * fp)1411 ctf_max_id(ctf_file_t *fp)
1412 {
1413 int child = (fp->ctf_flags & LCTF_CHILD);
1414 return (fp->ctf_typemax + (child ? CTF_CHILD_START : 0));
1415 }
1416
1417 ulong_t
ctf_nr_syms(ctf_file_t * fp)1418 ctf_nr_syms(ctf_file_t *fp)
1419 {
1420 return (fp->ctf_nsyms);
1421 }
1422