libctf: fix old ChangeLog typo
[deliverable/binutils-gdb.git] / libctf / ctf-types.c
CommitLineData
316afdb1 1/* Type handling functions.
250d07de 2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
316afdb1
NA
3
4 This file is part of libctf.
5
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
19
20#include <ctf-impl.h>
688d28f6 21#include <assert.h>
316afdb1
NA
22#include <string.h>
23
24/* Determine whether a type is a parent or a child. */
25
26int
139633c3 27ctf_type_isparent (ctf_dict_t *fp, ctf_id_t id)
316afdb1
NA
28{
29 return (LCTF_TYPE_ISPARENT (fp, id));
30}
31
32int
139633c3 33ctf_type_ischild (ctf_dict_t * fp, ctf_id_t id)
316afdb1
NA
34{
35 return (LCTF_TYPE_ISCHILD (fp, id));
36}
37
38/* Iterate over the members of a STRUCT or UNION. We pass the name, member
39 type, and offset of each member to the specified callback function. */
40
41int
139633c3 42ctf_member_iter (ctf_dict_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
316afdb1 43{
6c3a3877
NA
44 ctf_next_t *i = NULL;
45 ssize_t offset;
46 const char *name;
47 ctf_id_t membtype;
316afdb1
NA
48 int rc;
49
6c3a3877 50 while ((offset = ctf_member_next (fp, type, &i, &name, &membtype, 0)) >= 0)
316afdb1 51 {
6c3a3877 52 if ((rc = func (name, membtype, offset, arg)) != 0)
316afdb1 53 {
6c3a3877
NA
54 ctf_next_destroy (i);
55 return rc;
316afdb1
NA
56 }
57 }
6c3a3877
NA
58 if (ctf_errno (fp) != ECTF_NEXT_END)
59 return -1; /* errno is set for us. */
316afdb1
NA
60
61 return 0;
62}
63
688d28f6
NA
64/* Iterate over the members of a STRUCT or UNION, returning each member's
65 offset and optionally name and member type in turn. On end-of-iteration,
6c3a3877 66 returns -1. If FLAGS is CTF_MN_RECURSE, recurse into unnamed members. */
688d28f6
NA
67
68ssize_t
139633c3 69ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
6c3a3877 70 const char **name, ctf_id_t *membtype, int flags)
688d28f6 71{
139633c3 72 ctf_dict_t *ofp = fp;
688d28f6
NA
73 uint32_t kind;
74 ssize_t offset;
75 ctf_next_t *i = *it;
76
77 if (!i)
78 {
79 const ctf_type_t *tp;
80 ctf_dtdef_t *dtd;
6c3a3877 81 ssize_t increment;
688d28f6
NA
82
83 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
84 return -1; /* errno is set for us. */
85
86 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
87 return -1; /* errno is set for us. */
88
89 if ((i = ctf_next_create ()) == NULL)
90 return ctf_set_errno (ofp, ENOMEM);
91 i->cu.ctn_fp = ofp;
92
6c3a3877 93 (void) ctf_get_ctt_size (fp, tp, &i->ctn_size, &increment);
688d28f6
NA
94 kind = LCTF_INFO_KIND (fp, tp->ctt_info);
95
96 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
97 {
98 ctf_next_destroy (i);
99 return (ctf_set_errno (ofp, ECTF_NOTSOU));
100 }
101
102 dtd = ctf_dynamic_type (fp, type);
103 i->ctn_iter_fun = (void (*) (void)) ctf_member_next;
104
105 /* We depend below on the RDWR state indicating whether the DTD-related
106 fields or the DMD-related fields have been initialized. */
107
108 assert ((dtd && (fp->ctf_flags & LCTF_RDWR))
109 || (!dtd && (!(fp->ctf_flags & LCTF_RDWR))));
110
111 if (dtd == NULL)
112 {
113 i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info);
114
115 if (i->ctn_size < CTF_LSTRUCT_THRESH)
6c3a3877 116 i->u.ctn_mp = (const ctf_member_t *) ((uintptr_t) tp + increment);
688d28f6 117 else
6c3a3877 118 i->u.ctn_lmp = (const ctf_lmember_t *) ((uintptr_t) tp + increment);
688d28f6
NA
119 }
120 else
121 i->u.ctn_dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
122
123 *it = i;
124 }
125
126 if ((void (*) (void)) ctf_member_next != i->ctn_iter_fun)
127 return (ctf_set_errno (ofp, ECTF_NEXT_WRONGFUN));
128
129 if (ofp != i->cu.ctn_fp)
130 return (ctf_set_errno (ofp, ECTF_NEXT_WRONGFP));
131
132 /* Resolve to the native dict of this type. */
133 if ((fp = ctf_get_dict (ofp, type)) == NULL)
134 return (ctf_set_errno (ofp, ECTF_NOPARENT));
135
6c3a3877
NA
136 /* When we hit an unnamed struct/union member, we set ctn_type to indicate
137 that we are inside one, then return the unnamed member: on the next call,
138 we must skip over top-level member iteration in favour of iteration within
139 the sub-struct until it later turns out that that iteration has ended. */
688d28f6 140
6c3a3877
NA
141 retry:
142 if (!i->ctn_type)
143 {
144 if (!(fp->ctf_flags & LCTF_RDWR))
688d28f6 145 {
6c3a3877
NA
146 if (i->ctn_n == 0)
147 goto end_iter;
148
149 if (i->ctn_size < CTF_LSTRUCT_THRESH)
150 {
151 const char *membname = ctf_strptr (fp, i->u.ctn_mp->ctm_name);
152
153 if (name)
154 *name = membname;
155 if (membtype)
156 *membtype = i->u.ctn_mp->ctm_type;
157 offset = i->u.ctn_mp->ctm_offset;
158
159 if (membname[0] == 0
160 && (ctf_type_kind (fp, i->u.ctn_mp->ctm_type) == CTF_K_STRUCT
161 || ctf_type_kind (fp, i->u.ctn_mp->ctm_type) == CTF_K_UNION))
162 i->ctn_type = i->u.ctn_mp->ctm_type;
163
164 i->u.ctn_mp++;
165 }
166 else
167 {
168 const char *membname = ctf_strptr (fp, i->u.ctn_lmp->ctlm_name);
169
170 if (name)
171 *name = membname;
172 if (membtype)
173 *membtype = i->u.ctn_lmp->ctlm_type;
174 offset = (unsigned long) CTF_LMEM_OFFSET (i->u.ctn_lmp);
175
176 if (membname[0] == 0
177 && (ctf_type_kind (fp, i->u.ctn_lmp->ctlm_type) == CTF_K_STRUCT
178 || ctf_type_kind (fp, i->u.ctn_lmp->ctlm_type) == CTF_K_UNION))
179 i->ctn_type = i->u.ctn_lmp->ctlm_type;
180
181 i->u.ctn_lmp++;
182 }
183 i->ctn_n--;
688d28f6
NA
184 }
185 else
186 {
6c3a3877
NA
187 if (i->u.ctn_dmd == NULL)
188 goto end_iter;
189 /* The dmd contains a NULL for unnamed dynamic members. Don't inflict
190 this on our callers. */
688d28f6 191 if (name)
6c3a3877
NA
192 {
193 if (i->u.ctn_dmd->dmd_name)
194 *name = i->u.ctn_dmd->dmd_name;
195 else
196 *name = "";
197 }
688d28f6 198 if (membtype)
6c3a3877
NA
199 *membtype = i->u.ctn_dmd->dmd_type;
200 offset = i->u.ctn_dmd->dmd_offset;
201
202 if (i->u.ctn_dmd->dmd_name == NULL
203 && (ctf_type_kind (fp, i->u.ctn_dmd->dmd_type) == CTF_K_STRUCT
204 || ctf_type_kind (fp, i->u.ctn_dmd->dmd_type) == CTF_K_UNION))
205 i->ctn_type = i->u.ctn_dmd->dmd_type;
206
207 i->u.ctn_dmd = ctf_list_next (i->u.ctn_dmd);
688d28f6 208 }
6c3a3877
NA
209
210 /* The callers might want automatic recursive sub-struct traversal. */
211 if (!(flags & CTF_MN_RECURSE))
212 i->ctn_type = 0;
213
214 /* Sub-struct traversal starting? Take note of the offset of this member,
215 for later boosting of sub-struct members' offsets. */
216 if (i->ctn_type)
217 i->ctn_increment = offset;
688d28f6 218 }
6c3a3877 219 /* Traversing a sub-struct? Just return it, with the offset adjusted. */
688d28f6
NA
220 else
221 {
6c3a3877
NA
222 ssize_t ret = ctf_member_next (fp, i->ctn_type, &i->ctn_next, name,
223 membtype, flags);
224
225 if (ret >= 0)
226 return ret + i->ctn_increment;
227
228 if (ctf_errno (fp) != ECTF_NEXT_END)
229 {
230 ctf_next_destroy (i);
231 *it = NULL;
232 i->ctn_type = 0;
233 return ret; /* errno is set for us. */
234 }
235
236 if (!ctf_assert (fp, (i->ctn_next == NULL)))
237 return -1; /* errno is set for us. */
238
239 i->ctn_type = 0;
240 /* This sub-struct has ended: on to the next real member. */
241 goto retry;
688d28f6
NA
242 }
243
244 return offset;
245
246 end_iter:
247 ctf_next_destroy (i);
248 *it = NULL;
249 return ctf_set_errno (ofp, ECTF_NEXT_END);
250}
251
316afdb1
NA
252/* Iterate over the members of an ENUM. We pass the string name and associated
253 integer value of each enum element to the specified callback function. */
254
255int
139633c3 256ctf_enum_iter (ctf_dict_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
316afdb1 257{
139633c3 258 ctf_dict_t *ofp = fp;
316afdb1
NA
259 const ctf_type_t *tp;
260 const ctf_enum_t *ep;
676c3ecb 261 ctf_dtdef_t *dtd;
316afdb1
NA
262 ssize_t increment;
263 uint32_t n;
264 int rc;
265
266 if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
a0486bac 267 return -1; /* errno is set for us. */
316afdb1
NA
268
269 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
a0486bac 270 return -1; /* errno is set for us. */
316afdb1
NA
271
272 if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
273 return (ctf_set_errno (ofp, ECTF_NOTENUM));
274
275 (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
276
676c3ecb
NA
277 if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
278 {
279 ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
316afdb1 280
676c3ecb
NA
281 for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
282 {
283 const char *name = ctf_strptr (fp, ep->cte_name);
284 if ((rc = func (name, ep->cte_value, arg)) != 0)
285 return rc;
286 }
287 }
288 else
316afdb1 289 {
676c3ecb
NA
290 ctf_dmdef_t *dmd;
291
292 for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
293 dmd != NULL; dmd = ctf_list_next (dmd))
294 {
295 if ((rc = func (dmd->dmd_name, dmd->dmd_value, arg)) != 0)
296 return rc;
297 }
316afdb1
NA
298 }
299
300 return 0;
301}
302
688d28f6
NA
303/* Iterate over the members of an enum TYPE, returning each enumerand's NAME or
304 NULL at end of iteration or error, and optionally passing back the
305 enumerand's integer VALue. */
306
307const char *
139633c3 308ctf_enum_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
688d28f6
NA
309 int *val)
310{
139633c3 311 ctf_dict_t *ofp = fp;
688d28f6
NA
312 uint32_t kind;
313 const char *name;
314 ctf_next_t *i = *it;
315
316 if (!i)
317 {
318 const ctf_type_t *tp;
319 ctf_dtdef_t *dtd;
320
321 if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
322 return NULL; /* errno is set for us. */
323
324 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
325 return NULL; /* errno is set for us. */
326
327 if ((i = ctf_next_create ()) == NULL)
328 {
329 ctf_set_errno (ofp, ENOMEM);
330 return NULL;
331 }
332 i->cu.ctn_fp = ofp;
333
334 (void) ctf_get_ctt_size (fp, tp, NULL,
335 &i->ctn_increment);
336 kind = LCTF_INFO_KIND (fp, tp->ctt_info);
337
338 if (kind != CTF_K_ENUM)
339 {
340 ctf_next_destroy (i);
341 ctf_set_errno (ofp, ECTF_NOTENUM);
342 return NULL;
343 }
344
345 dtd = ctf_dynamic_type (fp, type);
346 i->ctn_iter_fun = (void (*) (void)) ctf_enum_next;
347
348 /* We depend below on the RDWR state indicating whether the DTD-related
349 fields or the DMD-related fields have been initialized. */
350
351 assert ((dtd && (fp->ctf_flags & LCTF_RDWR))
352 || (!dtd && (!(fp->ctf_flags & LCTF_RDWR))));
353
354 if (dtd == NULL)
355 {
356 i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info);
357
358 i->u.ctn_en = (const ctf_enum_t *) ((uintptr_t) tp +
359 i->ctn_increment);
360 }
361 else
362 i->u.ctn_dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
363
364 *it = i;
365 }
366
367 if ((void (*) (void)) ctf_enum_next != i->ctn_iter_fun)
368 {
369 ctf_set_errno (ofp, ECTF_NEXT_WRONGFUN);
370 return NULL;
371 }
372
373 if (ofp != i->cu.ctn_fp)
374 {
375 ctf_set_errno (ofp, ECTF_NEXT_WRONGFP);
376 return NULL;
377 }
378
379 /* Resolve to the native dict of this type. */
380 if ((fp = ctf_get_dict (ofp, type)) == NULL)
381 {
382 ctf_set_errno (ofp, ECTF_NOPARENT);
383 return NULL;
384 }
385
386 if (!(fp->ctf_flags & LCTF_RDWR))
387 {
388 if (i->ctn_n == 0)
389 goto end_iter;
390
391 name = ctf_strptr (fp, i->u.ctn_en->cte_name);
392 if (val)
393 *val = i->u.ctn_en->cte_value;
394 i->u.ctn_en++;
395 i->ctn_n--;
396 }
397 else
398 {
399 if (i->u.ctn_dmd == NULL)
400 goto end_iter;
401
402 name = i->u.ctn_dmd->dmd_name;
403 if (val)
404 *val = i->u.ctn_dmd->dmd_value;
405 i->u.ctn_dmd = ctf_list_next (i->u.ctn_dmd);
406 }
407
408 return name;
409
410 end_iter:
411 ctf_next_destroy (i);
412 *it = NULL;
413 ctf_set_errno (ofp, ECTF_NEXT_END);
414 return NULL;
415}
416
139633c3 417/* Iterate over every root (user-visible) type in the given CTF dict.
688d28f6
NA
418 We pass the type ID of each type to the specified callback function.
419
420 Does not traverse parent types: you have to do that explicitly. This is by
421 design, to avoid traversing them more than once if traversing many children
422 of a single parent. */
316afdb1
NA
423
424int
139633c3 425ctf_type_iter (ctf_dict_t *fp, ctf_type_f *func, void *arg)
316afdb1
NA
426{
427 ctf_id_t id, max = fp->ctf_typemax;
428 int rc, child = (fp->ctf_flags & LCTF_CHILD);
429
430 for (id = 1; id <= max; id++)
431 {
432 const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
433 if (LCTF_INFO_ISROOT (fp, tp->ctt_info)
434 && (rc = func (LCTF_INDEX_TO_TYPE (fp, id, child), arg)) != 0)
435 return rc;
436 }
437
438 return 0;
439}
440
139633c3 441/* Iterate over every type in the given CTF dict, user-visible or not.
688d28f6
NA
442 We pass the type ID of each type to the specified callback function.
443
444 Does not traverse parent types: you have to do that explicitly. This is by
445 design, to avoid traversing them more than once if traversing many children
446 of a single parent. */
0ac62312
NA
447
448int
139633c3 449ctf_type_iter_all (ctf_dict_t *fp, ctf_type_all_f *func, void *arg)
0ac62312
NA
450{
451 ctf_id_t id, max = fp->ctf_typemax;
452 int rc, child = (fp->ctf_flags & LCTF_CHILD);
453
454 for (id = 1; id <= max; id++)
455 {
456 const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
457 if ((rc = func (LCTF_INDEX_TO_TYPE (fp, id, child),
458 LCTF_INFO_ISROOT(fp, tp->ctt_info)
459 ? CTF_ADD_ROOT : CTF_ADD_NONROOT, arg) != 0))
460 return rc;
461 }
462
463 return 0;
464}
465
139633c3 466/* Iterate over every type in the given CTF dict, optionally including
688d28f6
NA
467 non-user-visible types, returning each type ID and hidden flag in turn.
468 Returns CTF_ERR on end of iteration or error.
469
470 Does not traverse parent types: you have to do that explicitly. This is by
471 design, to avoid traversing them more than once if traversing many children
472 of a single parent. */
473
474ctf_id_t
139633c3 475ctf_type_next (ctf_dict_t *fp, ctf_next_t **it, int *flag, int want_hidden)
688d28f6
NA
476{
477 ctf_next_t *i = *it;
478
479 if (!i)
480 {
481 if ((i = ctf_next_create ()) == NULL)
482 return ctf_set_errno (fp, ENOMEM);
483
484 i->cu.ctn_fp = fp;
485 i->ctn_type = 1;
486 i->ctn_iter_fun = (void (*) (void)) ctf_type_next;
487 *it = i;
488 }
489
490 if ((void (*) (void)) ctf_type_next != i->ctn_iter_fun)
491 return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN));
492
493 if (fp != i->cu.ctn_fp)
494 return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP));
495
496 while (i->ctn_type <= fp->ctf_typemax)
497 {
498 const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR (fp, i->ctn_type);
499
500 if ((!want_hidden) && (!LCTF_INFO_ISROOT (fp, tp->ctt_info)))
501 {
502 i->ctn_type++;
503 continue;
504 }
505
506 if (flag)
507 *flag = LCTF_INFO_ISROOT (fp, tp->ctt_info);
508 return LCTF_INDEX_TO_TYPE (fp, i->ctn_type++, fp->ctf_flags & LCTF_CHILD);
509 }
510 ctf_next_destroy (i);
511 *it = NULL;
512 return ctf_set_errno (fp, ECTF_NEXT_END);
513}
514
139633c3 515/* Iterate over every variable in the given CTF dict, in arbitrary order.
316afdb1
NA
516 We pass the name of each variable to the specified callback function. */
517
518int
139633c3 519ctf_variable_iter (ctf_dict_t *fp, ctf_variable_f *func, void *arg)
316afdb1 520{
316afdb1
NA
521 int rc;
522
523 if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL))
b7190c82 524 return (ctf_set_errno (fp, ECTF_NOPARENT));
316afdb1 525
676c3ecb
NA
526 if (!(fp->ctf_flags & LCTF_RDWR))
527 {
528 unsigned long i;
529 for (i = 0; i < fp->ctf_nvars; i++)
530 if ((rc = func (ctf_strptr (fp, fp->ctf_vars[i].ctv_name),
531 fp->ctf_vars[i].ctv_type, arg)) != 0)
532 return rc;
533 }
534 else
535 {
536 ctf_dvdef_t *dvd;
537
538 for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL;
539 dvd = ctf_list_next (dvd))
540 {
541 if ((rc = func (dvd->dvd_name, dvd->dvd_type, arg)) != 0)
542 return rc;
543 }
544 }
316afdb1
NA
545
546 return 0;
547}
548
139633c3 549/* Iterate over every variable in the given CTF dict, in arbitrary order,
688d28f6
NA
550 returning the name and type of each variable in turn. The name argument is
551 not optional. Returns CTF_ERR on end of iteration or error. */
552
553ctf_id_t
139633c3 554ctf_variable_next (ctf_dict_t *fp, ctf_next_t **it, const char **name)
688d28f6
NA
555{
556 ctf_next_t *i = *it;
557
558 if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL))
559 return (ctf_set_errno (fp, ECTF_NOPARENT));
560
561 if (!i)
562 {
563 if ((i = ctf_next_create ()) == NULL)
564 return ctf_set_errno (fp, ENOMEM);
565
566 i->cu.ctn_fp = fp;
567 i->ctn_iter_fun = (void (*) (void)) ctf_variable_next;
568 if (fp->ctf_flags & LCTF_RDWR)
569 i->u.ctn_dvd = ctf_list_next (&fp->ctf_dvdefs);
570 *it = i;
571 }
572
573 if ((void (*) (void)) ctf_variable_next != i->ctn_iter_fun)
574 return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN));
575
576 if (fp != i->cu.ctn_fp)
577 return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP));
578
579 if (!(fp->ctf_flags & LCTF_RDWR))
580 {
581 if (i->ctn_n >= fp->ctf_nvars)
582 goto end_iter;
583
584 *name = ctf_strptr (fp, fp->ctf_vars[i->ctn_n].ctv_name);
585 return fp->ctf_vars[i->ctn_n++].ctv_type;
586 }
587 else
588 {
589 ctf_id_t id;
590
591 if (i->u.ctn_dvd == NULL)
592 goto end_iter;
593
594 *name = i->u.ctn_dvd->dvd_name;
595 id = i->u.ctn_dvd->dvd_type;
596 i->u.ctn_dvd = ctf_list_next (i->u.ctn_dvd);
597 return id;
598 }
599
600 end_iter:
601 ctf_next_destroy (i);
602 *it = NULL;
603 return ctf_set_errno (fp, ECTF_NEXT_END);
604}
605
316afdb1
NA
606/* Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
607 RESTRICT nodes until we reach a "base" type node. This is useful when
608 we want to follow a type ID to a node that has members or a size. To guard
609 against infinite loops, we implement simplified cycle detection and check
610 each link against itself, the previous node, and the topmost node.
611
ffeece6a
NA
612 Does not drill down through slices to their contained type.
613
614 Callers of this function must not presume that a type it returns must have a
615 valid ctt_size: forwards do not, and must be separately handled. */
316afdb1
NA
616
617ctf_id_t
139633c3 618ctf_type_resolve (ctf_dict_t *fp, ctf_id_t type)
316afdb1
NA
619{
620 ctf_id_t prev = type, otype = type;
139633c3 621 ctf_dict_t *ofp = fp;
316afdb1
NA
622 const ctf_type_t *tp;
623
791915db
NA
624 if (type == 0)
625 return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE));
626
316afdb1
NA
627 while ((tp = ctf_lookup_by_id (&fp, type)) != NULL)
628 {
629 switch (LCTF_INFO_KIND (fp, tp->ctt_info))
630 {
631 case CTF_K_TYPEDEF:
632 case CTF_K_VOLATILE:
633 case CTF_K_CONST:
634 case CTF_K_RESTRICT:
635 if (tp->ctt_type == type || tp->ctt_type == otype
636 || tp->ctt_type == prev)
637 {
926c9e76
NA
638 ctf_err_warn (ofp, 0, ECTF_CORRUPT, _("type %lx cycle detected"),
639 otype);
316afdb1
NA
640 return (ctf_set_errno (ofp, ECTF_CORRUPT));
641 }
642 prev = type;
643 type = tp->ctt_type;
644 break;
645 default:
646 return type;
647 }
791915db
NA
648 if (type == 0)
649 return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE));
316afdb1
NA
650 }
651
652 return CTF_ERR; /* errno is set for us. */
653}
654
655/* Like ctf_type_resolve(), but traverse down through slices to their contained
656 type. */
657
658ctf_id_t
139633c3 659ctf_type_resolve_unsliced (ctf_dict_t *fp, ctf_id_t type)
316afdb1
NA
660{
661 const ctf_type_t *tp;
662
663 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
664 return -1;
665
666 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
667 return CTF_ERR; /* errno is set for us. */
668
669 if ((LCTF_INFO_KIND (fp, tp->ctt_info)) == CTF_K_SLICE)
670 return ctf_type_reference (fp, type);
671 return type;
672}
673
1136c379
NA
674/* Return the native dict of a given type: if called on a child and the
675 type is in the parent, return the parent. Needed if you plan to access
676 the type directly, without using the API. */
677ctf_dict_t *
678ctf_get_dict (ctf_dict_t *fp, ctf_id_t type)
679{
680 if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, type))
681 return fp->ctf_parent;
682
683 return fp;
684}
685
676c3ecb
NA
686/* Look up a name in the given name table, in the appropriate hash given the
687 kind of the identifier. The name is a raw, undecorated identifier. */
688
139633c3 689ctf_id_t ctf_lookup_by_rawname (ctf_dict_t *fp, int kind, const char *name)
676c3ecb
NA
690{
691 return ctf_lookup_by_rawhash (fp, ctf_name_table (fp, kind), name);
692}
693
694/* Look up a name in the given name table, in the appropriate hash given the
695 readability state of the dictionary. The name is a raw, undecorated
696 identifier. */
697
139633c3 698ctf_id_t ctf_lookup_by_rawhash (ctf_dict_t *fp, ctf_names_t *np, const char *name)
676c3ecb
NA
699{
700 ctf_id_t id;
701
702 if (fp->ctf_flags & LCTF_RDWR)
8c419a91 703 id = (ctf_id_t) (uintptr_t) ctf_dynhash_lookup (np->ctn_writable, name);
676c3ecb
NA
704 else
705 id = ctf_hash_lookup_type (np->ctn_readonly, fp, name);
706 return id;
707}
708
96e3ec29 709/* Lookup the given type ID and return its name as a new dynamically-allocated
316afdb1
NA
710 string. */
711
712char *
139633c3 713ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
316afdb1
NA
714{
715 ctf_decl_t cd;
716 ctf_decl_node_t *cdp;
717 ctf_decl_prec_t prec, lp, rp;
718 int ptr, arr;
719 uint32_t k;
720 char *buf;
721
722 if (fp == NULL && type == CTF_ERR)
723 return NULL; /* Simplify caller code by permitting CTF_ERR. */
724
725 ctf_decl_init (&cd);
726 ctf_decl_push (&cd, fp, type);
727
728 if (cd.cd_err != 0)
729 {
730 ctf_decl_fini (&cd);
731 ctf_set_errno (fp, cd.cd_err);
732 return NULL;
733 }
734
735 /* If the type graph's order conflicts with lexical precedence order
736 for pointers or arrays, then we need to surround the declarations at
737 the corresponding lexical precedence with parentheses. This can
738 result in either a parenthesized pointer (*) as in int (*)() or
739 int (*)[], or in a parenthesized pointer and array as in int (*[])(). */
740
741 ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
742 arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
743
744 rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
745 lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
746
747 k = CTF_K_POINTER; /* Avoid leading whitespace (see below). */
748
749 for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++)
750 {
751 for (cdp = ctf_list_next (&cd.cd_nodes[prec]);
752 cdp != NULL; cdp = ctf_list_next (cdp))
753 {
139633c3 754 ctf_dict_t *rfp = fp;
316afdb1
NA
755 const ctf_type_t *tp = ctf_lookup_by_id (&rfp, cdp->cd_type);
756 const char *name = ctf_strptr (rfp, tp->ctt_name);
757
758 if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
759 ctf_decl_sprintf (&cd, " ");
760
761 if (lp == prec)
762 {
763 ctf_decl_sprintf (&cd, "(");
764 lp = -1;
765 }
766
767 switch (cdp->cd_kind)
768 {
769 case CTF_K_INTEGER:
770 case CTF_K_FLOAT:
771 case CTF_K_TYPEDEF:
96e3ec29
NA
772 /* Integers, floats, and typedefs must always be named types. */
773
774 if (name[0] == '\0')
775 {
776 ctf_set_errno (fp, ECTF_CORRUPT);
777 ctf_decl_fini (&cd);
778 return NULL;
779 }
780
316afdb1
NA
781 ctf_decl_sprintf (&cd, "%s", name);
782 break;
783 case CTF_K_POINTER:
784 ctf_decl_sprintf (&cd, "*");
785 break;
786 case CTF_K_ARRAY:
787 ctf_decl_sprintf (&cd, "[%u]", cdp->cd_n);
788 break;
789 case CTF_K_FUNCTION:
c6e9a1e5
NA
790 {
791 size_t i;
792 ctf_funcinfo_t fi;
793 ctf_id_t *argv = NULL;
794
795 if (ctf_func_type_info (rfp, cdp->cd_type, &fi) < 0)
796 goto err; /* errno is set for us. */
797
798 if ((argv = calloc (fi.ctc_argc, sizeof (ctf_id_t *))) == NULL)
799 {
800 ctf_set_errno (rfp, errno);
801 goto err;
802 }
803
804 if (ctf_func_type_args (rfp, cdp->cd_type,
805 fi.ctc_argc, argv) < 0)
806 goto err; /* errno is set for us. */
807
808 ctf_decl_sprintf (&cd, "(*) (");
809 for (i = 0; i < fi.ctc_argc; i++)
810 {
811 char *arg = ctf_type_aname (rfp, argv[i]);
812
813 if (arg == NULL)
814 goto err; /* errno is set for us. */
815 ctf_decl_sprintf (&cd, "%s", arg);
816 free (arg);
817
818 if ((i < fi.ctc_argc - 1)
819 || (fi.ctc_flags & CTF_FUNC_VARARG))
820 ctf_decl_sprintf (&cd, ", ");
821 }
822
823 if (fi.ctc_flags & CTF_FUNC_VARARG)
824 ctf_decl_sprintf (&cd, "...");
825 ctf_decl_sprintf (&cd, ")");
826
827 free (argv);
828 break;
829
830 err:
831 free (argv);
832 ctf_decl_fini (&cd);
833 return NULL;
834 }
316afdb1
NA
835 break;
836 case CTF_K_STRUCT:
837 case CTF_K_FORWARD:
838 ctf_decl_sprintf (&cd, "struct %s", name);
839 break;
840 case CTF_K_UNION:
841 ctf_decl_sprintf (&cd, "union %s", name);
842 break;
843 case CTF_K_ENUM:
844 ctf_decl_sprintf (&cd, "enum %s", name);
845 break;
846 case CTF_K_VOLATILE:
847 ctf_decl_sprintf (&cd, "volatile");
848 break;
849 case CTF_K_CONST:
850 ctf_decl_sprintf (&cd, "const");
851 break;
852 case CTF_K_RESTRICT:
853 ctf_decl_sprintf (&cd, "restrict");
854 break;
316afdb1
NA
855 }
856
857 k = cdp->cd_kind;
858 }
859
860 if (rp == prec)
861 ctf_decl_sprintf (&cd, ")");
862 }
863
864 if (cd.cd_enomem)
865 (void) ctf_set_errno (fp, ENOMEM);
866
867 buf = ctf_decl_buf (&cd);
868
869 ctf_decl_fini (&cd);
870 return buf;
871}
872
873/* Lookup the given type ID and print a string name for it into buf. Return
874 the actual number of bytes (not including \0) needed to format the name. */
875
876ssize_t
139633c3 877ctf_type_lname (ctf_dict_t *fp, ctf_id_t type, char *buf, size_t len)
316afdb1
NA
878{
879 char *str = ctf_type_aname (fp, type);
1a6ab13e 880 size_t slen;
316afdb1
NA
881
882 if (str == NULL)
fa56cdcd 883 return CTF_ERR; /* errno is set for us. */
316afdb1 884
1a6ab13e 885 slen = strlen (str);
316afdb1
NA
886 snprintf (buf, len, "%s", str);
887 free (str);
888
889 if (slen >= len)
890 (void) ctf_set_errno (fp, ECTF_NAMELEN);
891
892 return slen;
893}
894
895/* Lookup the given type ID and print a string name for it into buf. If buf
896 is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us. */
897
898char *
139633c3 899ctf_type_name (ctf_dict_t *fp, ctf_id_t type, char *buf, size_t len)
316afdb1
NA
900{
901 ssize_t rv = ctf_type_lname (fp, type, buf, len);
902 return (rv >= 0 && (size_t) rv < len ? buf : NULL);
903}
904
01d93174 905/* Lookup the given type ID and return its raw, unadorned, undecorated name.
139633c3 906 The name will live as long as its ctf_dict_t does. */
12a0b67d 907
01d93174 908const char *
139633c3 909ctf_type_name_raw (ctf_dict_t *fp, ctf_id_t type)
12a0b67d
NA
910{
911 const ctf_type_t *tp;
912
913 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
914 return NULL; /* errno is set for us. */
915
01d93174
NA
916 return ctf_strraw (fp, tp->ctt_name);
917}
918
919/* Lookup the given type ID and return its raw, unadorned, undecorated name as a
920 new dynamically-allocated string. */
921
922char *
139633c3 923ctf_type_aname_raw (ctf_dict_t *fp, ctf_id_t type)
01d93174
NA
924{
925 const char *name = ctf_type_name_raw (fp, type);
926
927 if (name != NULL)
928 return strdup (name);
12a0b67d
NA
929
930 return NULL;
931}
932
316afdb1
NA
933/* Resolve the type down to a base type node, and then return the size
934 of the type storage in bytes. */
935
936ssize_t
139633c3 937ctf_type_size (ctf_dict_t *fp, ctf_id_t type)
316afdb1 938{
ffeece6a 939 ctf_dict_t *ofp = fp;
316afdb1
NA
940 const ctf_type_t *tp;
941 ssize_t size;
942 ctf_arinfo_t ar;
943
944 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
945 return -1; /* errno is set for us. */
946
947 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
948 return -1; /* errno is set for us. */
949
950 switch (LCTF_INFO_KIND (fp, tp->ctt_info))
951 {
952 case CTF_K_POINTER:
953 return fp->ctf_dmodel->ctd_pointer;
954
955 case CTF_K_FUNCTION:
956 return 0; /* Function size is only known by symtab. */
957
958 case CTF_K_ENUM:
959 return fp->ctf_dmodel->ctd_int;
960
961 case CTF_K_ARRAY:
962 /* ctf_add_array() does not directly encode the element size, but
963 requires the user to multiply to determine the element size.
964
965 If ctf_get_ctt_size() returns nonzero, then use the recorded
966 size instead. */
967
968 if ((size = ctf_get_ctt_size (fp, tp, NULL, NULL)) > 0)
969 return size;
970
ffeece6a
NA
971 if (ctf_array_info (ofp, type, &ar) < 0
972 || (size = ctf_type_size (ofp, ar.ctr_contents)) < 0)
316afdb1
NA
973 return -1; /* errno is set for us. */
974
975 return size * ar.ctr_nelems;
976
ffeece6a
NA
977 case CTF_K_FORWARD:
978 /* Forwards do not have a meaningful size. */
979 return (ctf_set_errno (ofp, ECTF_INCOMPLETE));
980
316afdb1
NA
981 default: /* including slices of enums, etc */
982 return (ctf_get_ctt_size (fp, tp, NULL, NULL));
983 }
984}
985
986/* Resolve the type down to a base type node, and then return the alignment
987 needed for the type storage in bytes.
988
989 XXX may need arch-dependent attention. */
990
991ssize_t
139633c3 992ctf_type_align (ctf_dict_t *fp, ctf_id_t type)
316afdb1
NA
993{
994 const ctf_type_t *tp;
139633c3 995 ctf_dict_t *ofp = fp;
316afdb1
NA
996 int kind;
997
998 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
999 return -1; /* errno is set for us. */
1000
1001 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1002 return -1; /* errno is set for us. */
1003
1004 kind = LCTF_INFO_KIND (fp, tp->ctt_info);
1005 switch (kind)
1006 {
1007 case CTF_K_POINTER:
1008 case CTF_K_FUNCTION:
1009 return fp->ctf_dmodel->ctd_pointer;
1010
1011 case CTF_K_ARRAY:
1012 {
1013 ctf_arinfo_t r;
ffeece6a 1014 if (ctf_array_info (ofp, type, &r) < 0)
316afdb1 1015 return -1; /* errno is set for us. */
ffeece6a 1016 return (ctf_type_align (ofp, r.ctr_contents));
316afdb1
NA
1017 }
1018
1019 case CTF_K_STRUCT:
1020 case CTF_K_UNION:
1021 {
1022 size_t align = 0;
1023 ctf_dtdef_t *dtd;
1024
1025 if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
1026 {
1027 uint32_t n = LCTF_INFO_VLEN (fp, tp->ctt_info);
1028 ssize_t size, increment;
1029 const void *vmp;
1030
1031 (void) ctf_get_ctt_size (fp, tp, &size, &increment);
1032 vmp = (unsigned char *) tp + increment;
1033
1034 if (kind == CTF_K_STRUCT)
1035 n = MIN (n, 1); /* Only use first member for structs. */
1036
1037 if (size < CTF_LSTRUCT_THRESH)
1038 {
1039 const ctf_member_t *mp = vmp;
1040 for (; n != 0; n--, mp++)
1041 {
ffeece6a 1042 ssize_t am = ctf_type_align (ofp, mp->ctm_type);
a0486bac 1043 align = MAX (align, (size_t) am);
316afdb1
NA
1044 }
1045 }
1046 else
1047 {
1048 const ctf_lmember_t *lmp = vmp;
1049 for (; n != 0; n--, lmp++)
1050 {
ffeece6a 1051 ssize_t am = ctf_type_align (ofp, lmp->ctlm_type);
a0486bac 1052 align = MAX (align, (size_t) am);
316afdb1
NA
1053 }
1054 }
1055 }
1056 else
1057 {
1058 ctf_dmdef_t *dmd;
1059
1060 for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
1061 dmd != NULL; dmd = ctf_list_next (dmd))
1062 {
ffeece6a 1063 ssize_t am = ctf_type_align (ofp, dmd->dmd_type);
a0486bac 1064 align = MAX (align, (size_t) am);
316afdb1
NA
1065 if (kind == CTF_K_STRUCT)
1066 break;
1067 }
1068 }
1069
1070 return align;
1071 }
1072
1073 case CTF_K_ENUM:
1074 return fp->ctf_dmodel->ctd_int;
1075
ffeece6a
NA
1076 case CTF_K_FORWARD:
1077 /* Forwards do not have a meaningful alignment. */
1078 return (ctf_set_errno (ofp, ECTF_INCOMPLETE));
1079
316afdb1
NA
1080 default: /* including slices of enums, etc */
1081 return (ctf_get_ctt_size (fp, tp, NULL, NULL));
1082 }
1083}
1084
1085/* Return the kind (CTF_K_* constant) for the specified type ID. */
1086
1087int
139633c3 1088ctf_type_kind_unsliced (ctf_dict_t *fp, ctf_id_t type)
316afdb1
NA
1089{
1090 const ctf_type_t *tp;
1091
1092 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
a0486bac 1093 return -1; /* errno is set for us. */
316afdb1
NA
1094
1095 return (LCTF_INFO_KIND (fp, tp->ctt_info));
1096}
1097
1098/* Return the kind (CTF_K_* constant) for the specified type ID.
1099 Slices are considered to be of the same kind as the type sliced. */
1100
1101int
139633c3 1102ctf_type_kind (ctf_dict_t *fp, ctf_id_t type)
316afdb1
NA
1103{
1104 int kind;
1105
a0486bac
JM
1106 if ((kind = ctf_type_kind_unsliced (fp, type)) < 0)
1107 return -1;
316afdb1
NA
1108
1109 if (kind == CTF_K_SLICE)
1110 {
1111 if ((type = ctf_type_reference (fp, type)) == CTF_ERR)
a0486bac 1112 return -1;
316afdb1
NA
1113 kind = ctf_type_kind_unsliced (fp, type);
1114 }
1115
1116 return kind;
1117}
1118
9b15cbb7
NA
1119/* Return the kind of this type, except, for forwards, return the kind of thing
1120 this is a forward to. */
1121int
139633c3 1122ctf_type_kind_forwarded (ctf_dict_t *fp, ctf_id_t type)
9b15cbb7
NA
1123{
1124 int kind;
1125 const ctf_type_t *tp;
1126
1127 if ((kind = ctf_type_kind (fp, type)) < 0)
1128 return -1; /* errno is set for us. */
1129
1130 if (kind != CTF_K_FORWARD)
1131 return kind;
1132
1133 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1134 return -1; /* errno is set for us. */
1135
1136 return tp->ctt_type;
1137}
1138
316afdb1
NA
1139/* If the type is one that directly references another type (such as POINTER),
1140 then return the ID of the type to which it refers. */
1141
1142ctf_id_t
139633c3 1143ctf_type_reference (ctf_dict_t *fp, ctf_id_t type)
316afdb1 1144{
139633c3 1145 ctf_dict_t *ofp = fp;
316afdb1
NA
1146 const ctf_type_t *tp;
1147
1148 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1149 return CTF_ERR; /* errno is set for us. */
1150
1151 switch (LCTF_INFO_KIND (fp, tp->ctt_info))
1152 {
1153 case CTF_K_POINTER:
1154 case CTF_K_TYPEDEF:
1155 case CTF_K_VOLATILE:
1156 case CTF_K_CONST:
1157 case CTF_K_RESTRICT:
1158 return tp->ctt_type;
1159 /* Slices store their type in an unusual place. */
1160 case CTF_K_SLICE:
1161 {
43706199 1162 ctf_dtdef_t *dtd;
316afdb1 1163 const ctf_slice_t *sp;
43706199
NA
1164
1165 if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
1166 {
1167 ssize_t increment;
1168
1169 (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
1170 sp = (const ctf_slice_t *) ((uintptr_t) tp + increment);
1171 }
1172 else
1173 sp = &dtd->dtd_u.dtu_slice;
1174
316afdb1
NA
1175 return sp->cts_type;
1176 }
1177 default:
1178 return (ctf_set_errno (ofp, ECTF_NOTREF));
1179 }
1180}
1181
1182/* Find a pointer to type by looking in fp->ctf_ptrtab. If we can't find a
1183 pointer to the given type, see if we can compute a pointer to the type
1184 resulting from resolving the type down to its base type and use that
1185 instead. This helps with cases where the CTF data includes "struct foo *"
1186 but not "foo_t *" and the user accesses "foo_t *" in the debugger.
1187
139633c3 1188 XXX what about parent dicts? */
316afdb1
NA
1189
1190ctf_id_t
139633c3 1191ctf_type_pointer (ctf_dict_t *fp, ctf_id_t type)
316afdb1 1192{
139633c3 1193 ctf_dict_t *ofp = fp;
316afdb1
NA
1194 ctf_id_t ntype;
1195
1196 if (ctf_lookup_by_id (&fp, type) == NULL)
1197 return CTF_ERR; /* errno is set for us. */
1198
1199 if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)]) != 0)
1200 return (LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
1201
1202 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
1203 return (ctf_set_errno (ofp, ECTF_NOTYPE));
1204
1205 if (ctf_lookup_by_id (&fp, type) == NULL)
1206 return (ctf_set_errno (ofp, ECTF_NOTYPE));
1207
1208 if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)]) != 0)
1209 return (LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
1210
1211 return (ctf_set_errno (ofp, ECTF_NOTYPE));
1212}
1213
1214/* Return the encoding for the specified INTEGER or FLOAT. */
1215
1216int
139633c3 1217ctf_type_encoding (ctf_dict_t *fp, ctf_id_t type, ctf_encoding_t *ep)
316afdb1 1218{
139633c3 1219 ctf_dict_t *ofp = fp;
316afdb1
NA
1220 ctf_dtdef_t *dtd;
1221 const ctf_type_t *tp;
1222 ssize_t increment;
1223 uint32_t data;
1224
1225 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
a0486bac 1226 return -1; /* errno is set for us. */
316afdb1
NA
1227
1228 if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
1229 {
9c1a2295
NA
1230 switch (LCTF_INFO_KIND (fp, tp->ctt_info))
1231 {
1232 case CTF_K_INTEGER:
1233 case CTF_K_FLOAT:
1234 *ep = dtd->dtd_u.dtu_enc;
1235 break;
1236 case CTF_K_SLICE:
1237 {
1238 const ctf_slice_t *slice;
1239 ctf_encoding_t underlying_en;
502e838e
NA
1240 ctf_id_t underlying;
1241
9c1a2295 1242 slice = &dtd->dtd_u.dtu_slice;
502e838e
NA
1243 underlying = ctf_type_resolve (fp, slice->cts_type);
1244 data = ctf_type_encoding (fp, underlying, &underlying_en);
9c1a2295 1245
9c1a2295
NA
1246 ep->cte_format = underlying_en.cte_format;
1247 ep->cte_offset = slice->cts_offset;
1248 ep->cte_bits = slice->cts_bits;
1249 break;
1250 }
1251 default:
1252 return (ctf_set_errno (ofp, ECTF_NOTINTFP));
1253 }
316afdb1
NA
1254 return 0;
1255 }
1256
1257 (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
1258
1259 switch (LCTF_INFO_KIND (fp, tp->ctt_info))
1260 {
1261 case CTF_K_INTEGER:
1262 data = *(const uint32_t *) ((uintptr_t) tp + increment);
1263 ep->cte_format = CTF_INT_ENCODING (data);
1264 ep->cte_offset = CTF_INT_OFFSET (data);
1265 ep->cte_bits = CTF_INT_BITS (data);
1266 break;
1267 case CTF_K_FLOAT:
1268 data = *(const uint32_t *) ((uintptr_t) tp + increment);
1269 ep->cte_format = CTF_FP_ENCODING (data);
1270 ep->cte_offset = CTF_FP_OFFSET (data);
1271 ep->cte_bits = CTF_FP_BITS (data);
1272 break;
1273 case CTF_K_SLICE:
1274 {
1275 const ctf_slice_t *slice;
1276 ctf_encoding_t underlying_en;
502e838e 1277 ctf_id_t underlying;
316afdb1
NA
1278
1279 slice = (ctf_slice_t *) ((uintptr_t) tp + increment);
502e838e
NA
1280 underlying = ctf_type_resolve (fp, slice->cts_type);
1281 data = ctf_type_encoding (fp, underlying, &underlying_en);
316afdb1
NA
1282
1283 ep->cte_format = underlying_en.cte_format;
1284 ep->cte_offset = slice->cts_offset;
1285 ep->cte_bits = slice->cts_bits;
1286 break;
1287 }
1288 default:
1289 return (ctf_set_errno (ofp, ECTF_NOTINTFP));
1290 }
1291
1292 return 0;
1293}
1294
1295int
139633c3 1296ctf_type_cmp (ctf_dict_t *lfp, ctf_id_t ltype, ctf_dict_t *rfp,
316afdb1
NA
1297 ctf_id_t rtype)
1298{
1299 int rval;
1300
1301 if (ltype < rtype)
1302 rval = -1;
1303 else if (ltype > rtype)
1304 rval = 1;
1305 else
1306 rval = 0;
1307
1308 if (lfp == rfp)
1309 return rval;
1310
1311 if (LCTF_TYPE_ISPARENT (lfp, ltype) && lfp->ctf_parent != NULL)
1312 lfp = lfp->ctf_parent;
1313
1314 if (LCTF_TYPE_ISPARENT (rfp, rtype) && rfp->ctf_parent != NULL)
1315 rfp = rfp->ctf_parent;
1316
1317 if (lfp < rfp)
1318 return -1;
1319
1320 if (lfp > rfp)
1321 return 1;
1322
1323 return rval;
1324}
1325
1326/* Return a boolean value indicating if two types are compatible. This function
1327 returns true if the two types are the same, or if they (or their ultimate
1328 base type) have the same encoding properties, or (for structs / unions /
1329 enums / forward declarations) if they have the same name and (for structs /
1330 unions) member count. */
1331
1332int
139633c3
NA
1333ctf_type_compat (ctf_dict_t *lfp, ctf_id_t ltype,
1334 ctf_dict_t *rfp, ctf_id_t rtype)
316afdb1
NA
1335{
1336 const ctf_type_t *ltp, *rtp;
1337 ctf_encoding_t le, re;
1338 ctf_arinfo_t la, ra;
1339 uint32_t lkind, rkind;
1340 int same_names = 0;
1341
1342 if (ctf_type_cmp (lfp, ltype, rfp, rtype) == 0)
1343 return 1;
1344
1345 ltype = ctf_type_resolve (lfp, ltype);
1346 lkind = ctf_type_kind (lfp, ltype);
1347
1348 rtype = ctf_type_resolve (rfp, rtype);
1349 rkind = ctf_type_kind (rfp, rtype);
1350
1351 ltp = ctf_lookup_by_id (&lfp, ltype);
1352 rtp = ctf_lookup_by_id (&rfp, rtype);
1353
1354 if (ltp != NULL && rtp != NULL)
1355 same_names = (strcmp (ctf_strptr (lfp, ltp->ctt_name),
1356 ctf_strptr (rfp, rtp->ctt_name)) == 0);
1357
1358 if (((lkind == CTF_K_ENUM) && (rkind == CTF_K_INTEGER)) ||
1359 ((rkind == CTF_K_ENUM) && (lkind == CTF_K_INTEGER)))
1360 return 1;
1361
1362 if (lkind != rkind)
1363 return 0;
1364
1365 switch (lkind)
1366 {
1367 case CTF_K_INTEGER:
1368 case CTF_K_FLOAT:
1369 memset (&le, 0, sizeof (le));
1370 memset (&re, 0, sizeof (re));
1371 return (ctf_type_encoding (lfp, ltype, &le) == 0
1372 && ctf_type_encoding (rfp, rtype, &re) == 0
1373 && memcmp (&le, &re, sizeof (ctf_encoding_t)) == 0);
1374 case CTF_K_POINTER:
1375 return (ctf_type_compat (lfp, ctf_type_reference (lfp, ltype),
1376 rfp, ctf_type_reference (rfp, rtype)));
1377 case CTF_K_ARRAY:
1378 return (ctf_array_info (lfp, ltype, &la) == 0
1379 && ctf_array_info (rfp, rtype, &ra) == 0
1380 && la.ctr_nelems == ra.ctr_nelems
1381 && ctf_type_compat (lfp, la.ctr_contents, rfp, ra.ctr_contents)
1382 && ctf_type_compat (lfp, la.ctr_index, rfp, ra.ctr_index));
1383 case CTF_K_STRUCT:
1384 case CTF_K_UNION:
1385 return (same_names && (ctf_type_size (lfp, ltype)
1386 == ctf_type_size (rfp, rtype)));
1387 case CTF_K_ENUM:
1388 {
1389 int lencoded, rencoded;
1390 lencoded = ctf_type_encoding (lfp, ltype, &le);
1391 rencoded = ctf_type_encoding (rfp, rtype, &re);
1392
1393 if ((lencoded != rencoded) ||
1394 ((lencoded == 0) && memcmp (&le, &re, sizeof (ctf_encoding_t)) != 0))
1395 return 0;
1396 }
1397 /* FALLTHRU */
1398 case CTF_K_FORWARD:
1399 return same_names; /* No other checks required for these type kinds. */
1400 default:
1401 return 0; /* Should not get here since we did a resolve. */
1402 }
1403}
1404
e0325e2c 1405/* Return the number of members in a STRUCT or UNION, or the number of
6c3a3877 1406 enumerators in an ENUM. The count does not include unnamed sub-members. */
e0325e2c
NA
1407
1408int
139633c3 1409ctf_member_count (ctf_dict_t *fp, ctf_id_t type)
e0325e2c 1410{
139633c3 1411 ctf_dict_t *ofp = fp;
e0325e2c
NA
1412 const ctf_type_t *tp;
1413 uint32_t kind;
1414
1415 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
1416 return -1; /* errno is set for us. */
1417
1418 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1419 return -1; /* errno is set for us. */
1420
1421 kind = LCTF_INFO_KIND (fp, tp->ctt_info);
1422
1423 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION && kind != CTF_K_ENUM)
1424 return (ctf_set_errno (ofp, ECTF_NOTSUE));
1425
1426 return LCTF_INFO_VLEN (fp, tp->ctt_info);
1427}
1428
316afdb1
NA
1429/* Return the type and offset for a given member of a STRUCT or UNION. */
1430
1431int
139633c3 1432ctf_member_info (ctf_dict_t *fp, ctf_id_t type, const char *name,
316afdb1
NA
1433 ctf_membinfo_t *mip)
1434{
139633c3 1435 ctf_dict_t *ofp = fp;
316afdb1 1436 const ctf_type_t *tp;
676c3ecb 1437 ctf_dtdef_t *dtd;
316afdb1
NA
1438 ssize_t size, increment;
1439 uint32_t kind, n;
1440
1441 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
a0486bac 1442 return -1; /* errno is set for us. */
316afdb1
NA
1443
1444 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
a0486bac 1445 return -1; /* errno is set for us. */
316afdb1
NA
1446
1447 (void) ctf_get_ctt_size (fp, tp, &size, &increment);
1448 kind = LCTF_INFO_KIND (fp, tp->ctt_info);
1449
1450 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
1451 return (ctf_set_errno (ofp, ECTF_NOTSOU));
1452
676c3ecb 1453 if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
316afdb1 1454 {
676c3ecb
NA
1455 if (size < CTF_LSTRUCT_THRESH)
1456 {
1457 const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
1458 increment);
316afdb1 1459
676c3ecb
NA
1460 for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
1461 {
6c3a3877
NA
1462 const char *membname = ctf_strptr (fp, mp->ctm_name);
1463
1464 if (membname[0] == 0
1465 && (ctf_type_kind (fp, mp->ctm_type) == CTF_K_STRUCT
1466 || ctf_type_kind (fp, mp->ctm_type) == CTF_K_UNION)
1467 && (ctf_member_info (fp, mp->ctm_type, name, mip) == 0))
1468 return 0;
1469
1470 if (strcmp (membname, name) == 0)
676c3ecb
NA
1471 {
1472 mip->ctm_type = mp->ctm_type;
1473 mip->ctm_offset = mp->ctm_offset;
1474 return 0;
1475 }
1476 }
1477 }
1478 else
316afdb1 1479 {
676c3ecb
NA
1480 const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
1481 increment);
1482
1483 for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
316afdb1 1484 {
6c3a3877
NA
1485 const char *membname = ctf_strptr (fp, lmp->ctlm_name);
1486
1487 if (membname[0] == 0
1488 && (ctf_type_kind (fp, lmp->ctlm_type) == CTF_K_STRUCT
1489 || ctf_type_kind (fp, lmp->ctlm_type) == CTF_K_UNION)
1490 && (ctf_member_info (fp, lmp->ctlm_type, name, mip) == 0))
1491 return 0;
1492
1493 if (strcmp (membname, name) == 0)
676c3ecb
NA
1494 {
1495 mip->ctm_type = lmp->ctlm_type;
1496 mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp);
1497 return 0;
1498 }
316afdb1
NA
1499 }
1500 }
1501 }
1502 else
1503 {
676c3ecb 1504 ctf_dmdef_t *dmd;
316afdb1 1505
676c3ecb
NA
1506 for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
1507 dmd != NULL; dmd = ctf_list_next (dmd))
316afdb1 1508 {
6c3a3877
NA
1509 if (dmd->dmd_name == NULL
1510 && (ctf_type_kind (fp, dmd->dmd_type) == CTF_K_STRUCT
1511 || ctf_type_kind (fp, dmd->dmd_type) == CTF_K_UNION)
1512 && (ctf_member_info (fp, dmd->dmd_type, name, mip) == 0))
1513 return 0;
1514
1515 if (dmd->dmd_name != NULL
1516 && strcmp (dmd->dmd_name, name) == 0)
316afdb1 1517 {
676c3ecb
NA
1518 mip->ctm_type = dmd->dmd_type;
1519 mip->ctm_offset = dmd->dmd_offset;
316afdb1
NA
1520 return 0;
1521 }
1522 }
1523 }
1524
1525 return (ctf_set_errno (ofp, ECTF_NOMEMBNAM));
1526}
1527
1528/* Return the array type, index, and size information for the specified ARRAY. */
1529
1530int
139633c3 1531ctf_array_info (ctf_dict_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
316afdb1 1532{
139633c3 1533 ctf_dict_t *ofp = fp;
316afdb1
NA
1534 const ctf_type_t *tp;
1535 const ctf_array_t *ap;
1536 const ctf_dtdef_t *dtd;
1537 ssize_t increment;
1538
1539 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
a0486bac 1540 return -1; /* errno is set for us. */
316afdb1
NA
1541
1542 if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ARRAY)
1543 return (ctf_set_errno (ofp, ECTF_NOTARRAY));
1544
1545 if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
1546 {
1547 *arp = dtd->dtd_u.dtu_arr;
1548 return 0;
1549 }
1550
1551 (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
1552
1553 ap = (const ctf_array_t *) ((uintptr_t) tp + increment);
1554 arp->ctr_contents = ap->cta_contents;
1555 arp->ctr_index = ap->cta_index;
1556 arp->ctr_nelems = ap->cta_nelems;
1557
1558 return 0;
1559}
1560
1561/* Convert the specified value to the corresponding enum tag name, if a
1562 matching name can be found. Otherwise NULL is returned. */
1563
1564const char *
139633c3 1565ctf_enum_name (ctf_dict_t *fp, ctf_id_t type, int value)
316afdb1 1566{
139633c3 1567 ctf_dict_t *ofp = fp;
316afdb1
NA
1568 const ctf_type_t *tp;
1569 const ctf_enum_t *ep;
676c3ecb 1570 const ctf_dtdef_t *dtd;
316afdb1
NA
1571 ssize_t increment;
1572 uint32_t n;
1573
1574 if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
1575 return NULL; /* errno is set for us. */
1576
1577 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1578 return NULL; /* errno is set for us. */
1579
1580 if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
1581 {
1582 (void) ctf_set_errno (ofp, ECTF_NOTENUM);
1583 return NULL;
1584 }
1585
1586 (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
1587
676c3ecb
NA
1588 if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
1589 {
1590 ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
316afdb1 1591
676c3ecb
NA
1592 for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
1593 {
1594 if (ep->cte_value == value)
1595 return (ctf_strptr (fp, ep->cte_name));
1596 }
1597 }
1598 else
316afdb1 1599 {
676c3ecb
NA
1600 ctf_dmdef_t *dmd;
1601
1602 for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
1603 dmd != NULL; dmd = ctf_list_next (dmd))
1604 {
1605 if (dmd->dmd_value == value)
1606 return dmd->dmd_name;
1607 }
316afdb1
NA
1608 }
1609
1610 (void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
1611 return NULL;
1612}
1613
1614/* Convert the specified enum tag name to the corresponding value, if a
1615 matching name can be found. Otherwise CTF_ERR is returned. */
1616
1617int
139633c3 1618ctf_enum_value (ctf_dict_t * fp, ctf_id_t type, const char *name, int *valp)
316afdb1 1619{
139633c3 1620 ctf_dict_t *ofp = fp;
316afdb1
NA
1621 const ctf_type_t *tp;
1622 const ctf_enum_t *ep;
676c3ecb 1623 const ctf_dtdef_t *dtd;
316afdb1
NA
1624 ssize_t increment;
1625 uint32_t n;
1626
1627 if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
a0486bac 1628 return -1; /* errno is set for us. */
316afdb1
NA
1629
1630 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
a0486bac 1631 return -1; /* errno is set for us. */
316afdb1
NA
1632
1633 if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
1634 {
1635 (void) ctf_set_errno (ofp, ECTF_NOTENUM);
a0486bac 1636 return -1;
316afdb1
NA
1637 }
1638
1639 (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
1640
1641 ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
1642
676c3ecb 1643 if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
316afdb1 1644 {
676c3ecb 1645 for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
316afdb1 1646 {
676c3ecb
NA
1647 if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0)
1648 {
1649 if (valp != NULL)
1650 *valp = ep->cte_value;
1651 return 0;
1652 }
1653 }
1654 }
1655 else
1656 {
1657 ctf_dmdef_t *dmd;
1658
1659 for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
1660 dmd != NULL; dmd = ctf_list_next (dmd))
1661 {
1662 if (strcmp (dmd->dmd_name, name) == 0)
1663 {
1664 if (valp != NULL)
1665 *valp = dmd->dmd_value;
1666 return 0;
1667 }
316afdb1
NA
1668 }
1669 }
1670
1671 (void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
a0486bac 1672 return -1;
316afdb1
NA
1673}
1674
12a0b67d
NA
1675/* Given a type ID relating to a function type, return info on return types and
1676 arg counts for that function. */
1677
1678int
139633c3 1679ctf_func_type_info (ctf_dict_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
12a0b67d
NA
1680{
1681 const ctf_type_t *tp;
1682 uint32_t kind;
1683 const uint32_t *args;
676c3ecb 1684 const ctf_dtdef_t *dtd;
12a0b67d
NA
1685 ssize_t size, increment;
1686
1687 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
1688 return -1; /* errno is set for us. */
1689
1690 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1691 return -1; /* errno is set for us. */
1692
1693 (void) ctf_get_ctt_size (fp, tp, &size, &increment);
1694 kind = LCTF_INFO_KIND (fp, tp->ctt_info);
1695
1696 if (kind != CTF_K_FUNCTION)
1697 return (ctf_set_errno (fp, ECTF_NOTFUNC));
1698
1699 fip->ctc_return = tp->ctt_type;
12a0b67d 1700 fip->ctc_flags = 0;
676c3ecb 1701 fip->ctc_argc = LCTF_INFO_VLEN (fp, tp->ctt_info);
12a0b67d 1702
676c3ecb
NA
1703 if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
1704 args = (uint32_t *) ((uintptr_t) tp + increment);
1705 else
afd78bd6 1706 args = dtd->dtd_u.dtu_argv;
12a0b67d
NA
1707
1708 if (fip->ctc_argc != 0 && args[fip->ctc_argc - 1] == 0)
1709 {
1710 fip->ctc_flags |= CTF_FUNC_VARARG;
1711 fip->ctc_argc--;
1712 }
1713
1714 return 0;
1715}
1716
afd78bd6 1717/* Given a type ID relating to a function type, return the arguments for the
12a0b67d
NA
1718 function. */
1719
1720int
139633c3 1721ctf_func_type_args (ctf_dict_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv)
12a0b67d
NA
1722{
1723 const ctf_type_t *tp;
1724 const uint32_t *args;
676c3ecb 1725 const ctf_dtdef_t *dtd;
12a0b67d
NA
1726 ssize_t size, increment;
1727 ctf_funcinfo_t f;
1728
1729 if (ctf_func_type_info (fp, type, &f) < 0)
1730 return -1; /* errno is set for us. */
1731
1732 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
1733 return -1; /* errno is set for us. */
1734
1735 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1736 return -1; /* errno is set for us. */
1737
1738 (void) ctf_get_ctt_size (fp, tp, &size, &increment);
1739
676c3ecb
NA
1740 if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
1741 args = (uint32_t *) ((uintptr_t) tp + increment);
1742 else
afd78bd6 1743 args = dtd->dtd_u.dtu_argv;
12a0b67d
NA
1744
1745 for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
1746 *argv++ = *args++;
1747
1748 return 0;
1749}
1750
316afdb1
NA
1751/* Recursively visit the members of any type. This function is used as the
1752 engine for ctf_type_visit, below. We resolve the input type, recursively
1753 invoke ourself for each type member if the type is a struct or union, and
1754 then invoke the callback function on the current type. If any callback
1755 returns non-zero, we abort and percolate the error code back up to the top. */
1756
1757static int
139633c3 1758ctf_type_rvisit (ctf_dict_t *fp, ctf_id_t type, ctf_visit_f *func,
316afdb1
NA
1759 void *arg, const char *name, unsigned long offset, int depth)
1760{
1761 ctf_id_t otype = type;
1762 const ctf_type_t *tp;
676c3ecb 1763 const ctf_dtdef_t *dtd;
316afdb1
NA
1764 ssize_t size, increment;
1765 uint32_t kind, n;
1766 int rc;
1767
1768 if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
a0486bac 1769 return -1; /* errno is set for us. */
316afdb1
NA
1770
1771 if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
a0486bac 1772 return -1; /* errno is set for us. */
316afdb1
NA
1773
1774 if ((rc = func (name, otype, offset, depth, arg)) != 0)
1775 return rc;
1776
1777 kind = LCTF_INFO_KIND (fp, tp->ctt_info);
1778
1779 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
1780 return 0;
1781
1782 (void) ctf_get_ctt_size (fp, tp, &size, &increment);
1783
676c3ecb 1784 if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
316afdb1 1785 {
676c3ecb 1786 if (size < CTF_LSTRUCT_THRESH)
316afdb1 1787 {
676c3ecb
NA
1788 const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
1789 increment);
1790
1791 for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
1792 {
1793 if ((rc = ctf_type_rvisit (fp, mp->ctm_type,
1794 func, arg, ctf_strptr (fp,
1795 mp->ctm_name),
1796 offset + mp->ctm_offset,
1797 depth + 1)) != 0)
1798 return rc;
1799 }
316afdb1 1800 }
676c3ecb
NA
1801 else
1802 {
1803 const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
1804 increment);
316afdb1 1805
676c3ecb
NA
1806 for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
1807 {
1808 if ((rc = ctf_type_rvisit (fp, lmp->ctlm_type,
1809 func, arg, ctf_strptr (fp,
1810 lmp->ctlm_name),
1811 offset + (unsigned long) CTF_LMEM_OFFSET (lmp),
1812 depth + 1)) != 0)
1813 return rc;
1814 }
1815 }
316afdb1
NA
1816 }
1817 else
1818 {
676c3ecb 1819 ctf_dmdef_t *dmd;
316afdb1 1820
676c3ecb
NA
1821 for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
1822 dmd != NULL; dmd = ctf_list_next (dmd))
316afdb1 1823 {
676c3ecb
NA
1824 if ((rc = ctf_type_rvisit (fp, dmd->dmd_type, func, arg,
1825 dmd->dmd_name, dmd->dmd_offset,
316afdb1
NA
1826 depth + 1)) != 0)
1827 return rc;
1828 }
1829 }
1830
1831 return 0;
1832}
1833
1834/* Recursively visit the members of any type. We pass the name, member
1835 type, and offset of each member to the specified callback function. */
1836int
139633c3 1837ctf_type_visit (ctf_dict_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
316afdb1
NA
1838{
1839 return (ctf_type_rvisit (fp, type, func, arg, "", 0, 0));
1840}
This page took 0.187528 seconds and 4 git commands to generate.