1*869ffda3Schristos /* Type handling functions.
2*869ffda3Schristos Copyright (C) 2019-2020 Free Software Foundation, Inc.
3*869ffda3Schristos
4*869ffda3Schristos This file is part of libctf.
5*869ffda3Schristos
6*869ffda3Schristos libctf is free software; you can redistribute it and/or modify it under
7*869ffda3Schristos the terms of the GNU General Public License as published by the Free
8*869ffda3Schristos Software Foundation; either version 3, or (at your option) any later
9*869ffda3Schristos version.
10*869ffda3Schristos
11*869ffda3Schristos This program is distributed in the hope that it will be useful, but
12*869ffda3Schristos WITHOUT ANY WARRANTY; without even the implied warranty of
13*869ffda3Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14*869ffda3Schristos See the GNU General Public License for more details.
15*869ffda3Schristos
16*869ffda3Schristos You should have received a copy of the GNU General Public License
17*869ffda3Schristos along with this program; see the file COPYING. If not see
18*869ffda3Schristos <http://www.gnu.org/licenses/>. */
19*869ffda3Schristos
20*869ffda3Schristos #include <ctf-impl.h>
21*869ffda3Schristos #include <string.h>
22*869ffda3Schristos
23*869ffda3Schristos /* Determine whether a type is a parent or a child. */
24*869ffda3Schristos
25*869ffda3Schristos int
ctf_type_isparent(ctf_file_t * fp,ctf_id_t id)26*869ffda3Schristos ctf_type_isparent (ctf_file_t *fp, ctf_id_t id)
27*869ffda3Schristos {
28*869ffda3Schristos return (LCTF_TYPE_ISPARENT (fp, id));
29*869ffda3Schristos }
30*869ffda3Schristos
31*869ffda3Schristos int
ctf_type_ischild(ctf_file_t * fp,ctf_id_t id)32*869ffda3Schristos ctf_type_ischild (ctf_file_t * fp, ctf_id_t id)
33*869ffda3Schristos {
34*869ffda3Schristos return (LCTF_TYPE_ISCHILD (fp, id));
35*869ffda3Schristos }
36*869ffda3Schristos
37*869ffda3Schristos /* Iterate over the members of a STRUCT or UNION. We pass the name, member
38*869ffda3Schristos type, and offset of each member to the specified callback function. */
39*869ffda3Schristos
40*869ffda3Schristos int
ctf_member_iter(ctf_file_t * fp,ctf_id_t type,ctf_member_f * func,void * arg)41*869ffda3Schristos ctf_member_iter (ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
42*869ffda3Schristos {
43*869ffda3Schristos ctf_file_t *ofp = fp;
44*869ffda3Schristos const ctf_type_t *tp;
45*869ffda3Schristos ctf_dtdef_t *dtd;
46*869ffda3Schristos ssize_t size, increment;
47*869ffda3Schristos uint32_t kind, n;
48*869ffda3Schristos int rc;
49*869ffda3Schristos
50*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
51*869ffda3Schristos return -1; /* errno is set for us. */
52*869ffda3Schristos
53*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
54*869ffda3Schristos return -1; /* errno is set for us. */
55*869ffda3Schristos
56*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, &size, &increment);
57*869ffda3Schristos kind = LCTF_INFO_KIND (fp, tp->ctt_info);
58*869ffda3Schristos
59*869ffda3Schristos if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
60*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTSOU));
61*869ffda3Schristos
62*869ffda3Schristos if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
63*869ffda3Schristos {
64*869ffda3Schristos if (size < CTF_LSTRUCT_THRESH)
65*869ffda3Schristos {
66*869ffda3Schristos const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
67*869ffda3Schristos increment);
68*869ffda3Schristos
69*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
70*869ffda3Schristos {
71*869ffda3Schristos const char *name = ctf_strptr (fp, mp->ctm_name);
72*869ffda3Schristos if ((rc = func (name, mp->ctm_type, mp->ctm_offset, arg)) != 0)
73*869ffda3Schristos return rc;
74*869ffda3Schristos }
75*869ffda3Schristos }
76*869ffda3Schristos else
77*869ffda3Schristos {
78*869ffda3Schristos const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
79*869ffda3Schristos increment);
80*869ffda3Schristos
81*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
82*869ffda3Schristos {
83*869ffda3Schristos const char *name = ctf_strptr (fp, lmp->ctlm_name);
84*869ffda3Schristos if ((rc = func (name, lmp->ctlm_type,
85*869ffda3Schristos (unsigned long) CTF_LMEM_OFFSET (lmp), arg)) != 0)
86*869ffda3Schristos return rc;
87*869ffda3Schristos }
88*869ffda3Schristos }
89*869ffda3Schristos }
90*869ffda3Schristos else
91*869ffda3Schristos {
92*869ffda3Schristos ctf_dmdef_t *dmd;
93*869ffda3Schristos
94*869ffda3Schristos for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
95*869ffda3Schristos dmd != NULL; dmd = ctf_list_next (dmd))
96*869ffda3Schristos {
97*869ffda3Schristos if ((rc = func (dmd->dmd_name, dmd->dmd_type,
98*869ffda3Schristos dmd->dmd_offset, arg)) != 0)
99*869ffda3Schristos return rc;
100*869ffda3Schristos }
101*869ffda3Schristos }
102*869ffda3Schristos
103*869ffda3Schristos return 0;
104*869ffda3Schristos }
105*869ffda3Schristos
106*869ffda3Schristos /* Iterate over the members of an ENUM. We pass the string name and associated
107*869ffda3Schristos integer value of each enum element to the specified callback function. */
108*869ffda3Schristos
109*869ffda3Schristos int
ctf_enum_iter(ctf_file_t * fp,ctf_id_t type,ctf_enum_f * func,void * arg)110*869ffda3Schristos ctf_enum_iter (ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
111*869ffda3Schristos {
112*869ffda3Schristos ctf_file_t *ofp = fp;
113*869ffda3Schristos const ctf_type_t *tp;
114*869ffda3Schristos const ctf_enum_t *ep;
115*869ffda3Schristos ctf_dtdef_t *dtd;
116*869ffda3Schristos ssize_t increment;
117*869ffda3Schristos uint32_t n;
118*869ffda3Schristos int rc;
119*869ffda3Schristos
120*869ffda3Schristos if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
121*869ffda3Schristos return -1; /* errno is set for us. */
122*869ffda3Schristos
123*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
124*869ffda3Schristos return -1; /* errno is set for us. */
125*869ffda3Schristos
126*869ffda3Schristos if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
127*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTENUM));
128*869ffda3Schristos
129*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
130*869ffda3Schristos
131*869ffda3Schristos if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
132*869ffda3Schristos {
133*869ffda3Schristos ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
134*869ffda3Schristos
135*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
136*869ffda3Schristos {
137*869ffda3Schristos const char *name = ctf_strptr (fp, ep->cte_name);
138*869ffda3Schristos if ((rc = func (name, ep->cte_value, arg)) != 0)
139*869ffda3Schristos return rc;
140*869ffda3Schristos }
141*869ffda3Schristos }
142*869ffda3Schristos else
143*869ffda3Schristos {
144*869ffda3Schristos ctf_dmdef_t *dmd;
145*869ffda3Schristos
146*869ffda3Schristos for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
147*869ffda3Schristos dmd != NULL; dmd = ctf_list_next (dmd))
148*869ffda3Schristos {
149*869ffda3Schristos if ((rc = func (dmd->dmd_name, dmd->dmd_value, arg)) != 0)
150*869ffda3Schristos return rc;
151*869ffda3Schristos }
152*869ffda3Schristos }
153*869ffda3Schristos
154*869ffda3Schristos return 0;
155*869ffda3Schristos }
156*869ffda3Schristos
157*869ffda3Schristos /* Iterate over every root (user-visible) type in the given CTF container.
158*869ffda3Schristos We pass the type ID of each type to the specified callback function. */
159*869ffda3Schristos
160*869ffda3Schristos int
ctf_type_iter(ctf_file_t * fp,ctf_type_f * func,void * arg)161*869ffda3Schristos ctf_type_iter (ctf_file_t *fp, ctf_type_f *func, void *arg)
162*869ffda3Schristos {
163*869ffda3Schristos ctf_id_t id, max = fp->ctf_typemax;
164*869ffda3Schristos int rc, child = (fp->ctf_flags & LCTF_CHILD);
165*869ffda3Schristos
166*869ffda3Schristos for (id = 1; id <= max; id++)
167*869ffda3Schristos {
168*869ffda3Schristos const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
169*869ffda3Schristos if (LCTF_INFO_ISROOT (fp, tp->ctt_info)
170*869ffda3Schristos && (rc = func (LCTF_INDEX_TO_TYPE (fp, id, child), arg)) != 0)
171*869ffda3Schristos return rc;
172*869ffda3Schristos }
173*869ffda3Schristos
174*869ffda3Schristos return 0;
175*869ffda3Schristos }
176*869ffda3Schristos
177*869ffda3Schristos /* Iterate over every type in the given CTF container, user-visible or not.
178*869ffda3Schristos We pass the type ID of each type to the specified callback function. */
179*869ffda3Schristos
180*869ffda3Schristos int
ctf_type_iter_all(ctf_file_t * fp,ctf_type_all_f * func,void * arg)181*869ffda3Schristos ctf_type_iter_all (ctf_file_t *fp, ctf_type_all_f *func, void *arg)
182*869ffda3Schristos {
183*869ffda3Schristos ctf_id_t id, max = fp->ctf_typemax;
184*869ffda3Schristos int rc, child = (fp->ctf_flags & LCTF_CHILD);
185*869ffda3Schristos
186*869ffda3Schristos for (id = 1; id <= max; id++)
187*869ffda3Schristos {
188*869ffda3Schristos const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
189*869ffda3Schristos if ((rc = func (LCTF_INDEX_TO_TYPE (fp, id, child),
190*869ffda3Schristos LCTF_INFO_ISROOT(fp, tp->ctt_info)
191*869ffda3Schristos ? CTF_ADD_ROOT : CTF_ADD_NONROOT, arg) != 0))
192*869ffda3Schristos return rc;
193*869ffda3Schristos }
194*869ffda3Schristos
195*869ffda3Schristos return 0;
196*869ffda3Schristos }
197*869ffda3Schristos
198*869ffda3Schristos /* Iterate over every variable in the given CTF container, in arbitrary order.
199*869ffda3Schristos We pass the name of each variable to the specified callback function. */
200*869ffda3Schristos
201*869ffda3Schristos int
ctf_variable_iter(ctf_file_t * fp,ctf_variable_f * func,void * arg)202*869ffda3Schristos ctf_variable_iter (ctf_file_t *fp, ctf_variable_f *func, void *arg)
203*869ffda3Schristos {
204*869ffda3Schristos int rc;
205*869ffda3Schristos
206*869ffda3Schristos if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL))
207*869ffda3Schristos return ECTF_NOPARENT;
208*869ffda3Schristos
209*869ffda3Schristos if (!(fp->ctf_flags & LCTF_RDWR))
210*869ffda3Schristos {
211*869ffda3Schristos unsigned long i;
212*869ffda3Schristos for (i = 0; i < fp->ctf_nvars; i++)
213*869ffda3Schristos if ((rc = func (ctf_strptr (fp, fp->ctf_vars[i].ctv_name),
214*869ffda3Schristos fp->ctf_vars[i].ctv_type, arg)) != 0)
215*869ffda3Schristos return rc;
216*869ffda3Schristos }
217*869ffda3Schristos else
218*869ffda3Schristos {
219*869ffda3Schristos ctf_dvdef_t *dvd;
220*869ffda3Schristos
221*869ffda3Schristos for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL;
222*869ffda3Schristos dvd = ctf_list_next (dvd))
223*869ffda3Schristos {
224*869ffda3Schristos if ((rc = func (dvd->dvd_name, dvd->dvd_type, arg)) != 0)
225*869ffda3Schristos return rc;
226*869ffda3Schristos }
227*869ffda3Schristos }
228*869ffda3Schristos
229*869ffda3Schristos return 0;
230*869ffda3Schristos }
231*869ffda3Schristos
232*869ffda3Schristos /* Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
233*869ffda3Schristos RESTRICT nodes until we reach a "base" type node. This is useful when
234*869ffda3Schristos we want to follow a type ID to a node that has members or a size. To guard
235*869ffda3Schristos against infinite loops, we implement simplified cycle detection and check
236*869ffda3Schristos each link against itself, the previous node, and the topmost node.
237*869ffda3Schristos
238*869ffda3Schristos Does not drill down through slices to their contained type. */
239*869ffda3Schristos
240*869ffda3Schristos ctf_id_t
ctf_type_resolve(ctf_file_t * fp,ctf_id_t type)241*869ffda3Schristos ctf_type_resolve (ctf_file_t *fp, ctf_id_t type)
242*869ffda3Schristos {
243*869ffda3Schristos ctf_id_t prev = type, otype = type;
244*869ffda3Schristos ctf_file_t *ofp = fp;
245*869ffda3Schristos const ctf_type_t *tp;
246*869ffda3Schristos
247*869ffda3Schristos if (type == 0)
248*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE));
249*869ffda3Schristos
250*869ffda3Schristos while ((tp = ctf_lookup_by_id (&fp, type)) != NULL)
251*869ffda3Schristos {
252*869ffda3Schristos switch (LCTF_INFO_KIND (fp, tp->ctt_info))
253*869ffda3Schristos {
254*869ffda3Schristos case CTF_K_TYPEDEF:
255*869ffda3Schristos case CTF_K_VOLATILE:
256*869ffda3Schristos case CTF_K_CONST:
257*869ffda3Schristos case CTF_K_RESTRICT:
258*869ffda3Schristos if (tp->ctt_type == type || tp->ctt_type == otype
259*869ffda3Schristos || tp->ctt_type == prev)
260*869ffda3Schristos {
261*869ffda3Schristos ctf_dprintf ("type %ld cycle detected\n", otype);
262*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_CORRUPT));
263*869ffda3Schristos }
264*869ffda3Schristos prev = type;
265*869ffda3Schristos type = tp->ctt_type;
266*869ffda3Schristos break;
267*869ffda3Schristos default:
268*869ffda3Schristos return type;
269*869ffda3Schristos }
270*869ffda3Schristos if (type == 0)
271*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE));
272*869ffda3Schristos }
273*869ffda3Schristos
274*869ffda3Schristos return CTF_ERR; /* errno is set for us. */
275*869ffda3Schristos }
276*869ffda3Schristos
277*869ffda3Schristos /* Like ctf_type_resolve(), but traverse down through slices to their contained
278*869ffda3Schristos type. */
279*869ffda3Schristos
280*869ffda3Schristos ctf_id_t
ctf_type_resolve_unsliced(ctf_file_t * fp,ctf_id_t type)281*869ffda3Schristos ctf_type_resolve_unsliced (ctf_file_t *fp, ctf_id_t type)
282*869ffda3Schristos {
283*869ffda3Schristos const ctf_type_t *tp;
284*869ffda3Schristos
285*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
286*869ffda3Schristos return -1;
287*869ffda3Schristos
288*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
289*869ffda3Schristos return CTF_ERR; /* errno is set for us. */
290*869ffda3Schristos
291*869ffda3Schristos if ((LCTF_INFO_KIND (fp, tp->ctt_info)) == CTF_K_SLICE)
292*869ffda3Schristos return ctf_type_reference (fp, type);
293*869ffda3Schristos return type;
294*869ffda3Schristos }
295*869ffda3Schristos
296*869ffda3Schristos /* Look up a name in the given name table, in the appropriate hash given the
297*869ffda3Schristos kind of the identifier. The name is a raw, undecorated identifier. */
298*869ffda3Schristos
ctf_lookup_by_rawname(ctf_file_t * fp,int kind,const char * name)299*869ffda3Schristos ctf_id_t ctf_lookup_by_rawname (ctf_file_t *fp, int kind, const char *name)
300*869ffda3Schristos {
301*869ffda3Schristos return ctf_lookup_by_rawhash (fp, ctf_name_table (fp, kind), name);
302*869ffda3Schristos }
303*869ffda3Schristos
304*869ffda3Schristos /* Look up a name in the given name table, in the appropriate hash given the
305*869ffda3Schristos readability state of the dictionary. The name is a raw, undecorated
306*869ffda3Schristos identifier. */
307*869ffda3Schristos
ctf_lookup_by_rawhash(ctf_file_t * fp,ctf_names_t * np,const char * name)308*869ffda3Schristos ctf_id_t ctf_lookup_by_rawhash (ctf_file_t *fp, ctf_names_t *np, const char *name)
309*869ffda3Schristos {
310*869ffda3Schristos ctf_id_t id;
311*869ffda3Schristos
312*869ffda3Schristos if (fp->ctf_flags & LCTF_RDWR)
313*869ffda3Schristos id = (ctf_id_t) ctf_dynhash_lookup (np->ctn_writable, name);
314*869ffda3Schristos else
315*869ffda3Schristos id = ctf_hash_lookup_type (np->ctn_readonly, fp, name);
316*869ffda3Schristos return id;
317*869ffda3Schristos }
318*869ffda3Schristos
319*869ffda3Schristos /* Lookup the given type ID and return its name as a new dynamcally-allocated
320*869ffda3Schristos string. */
321*869ffda3Schristos
322*869ffda3Schristos char *
ctf_type_aname(ctf_file_t * fp,ctf_id_t type)323*869ffda3Schristos ctf_type_aname (ctf_file_t *fp, ctf_id_t type)
324*869ffda3Schristos {
325*869ffda3Schristos ctf_decl_t cd;
326*869ffda3Schristos ctf_decl_node_t *cdp;
327*869ffda3Schristos ctf_decl_prec_t prec, lp, rp;
328*869ffda3Schristos int ptr, arr;
329*869ffda3Schristos uint32_t k;
330*869ffda3Schristos char *buf;
331*869ffda3Schristos
332*869ffda3Schristos if (fp == NULL && type == CTF_ERR)
333*869ffda3Schristos return NULL; /* Simplify caller code by permitting CTF_ERR. */
334*869ffda3Schristos
335*869ffda3Schristos ctf_decl_init (&cd);
336*869ffda3Schristos ctf_decl_push (&cd, fp, type);
337*869ffda3Schristos
338*869ffda3Schristos if (cd.cd_err != 0)
339*869ffda3Schristos {
340*869ffda3Schristos ctf_decl_fini (&cd);
341*869ffda3Schristos ctf_set_errno (fp, cd.cd_err);
342*869ffda3Schristos return NULL;
343*869ffda3Schristos }
344*869ffda3Schristos
345*869ffda3Schristos /* If the type graph's order conflicts with lexical precedence order
346*869ffda3Schristos for pointers or arrays, then we need to surround the declarations at
347*869ffda3Schristos the corresponding lexical precedence with parentheses. This can
348*869ffda3Schristos result in either a parenthesized pointer (*) as in int (*)() or
349*869ffda3Schristos int (*)[], or in a parenthesized pointer and array as in int (*[])(). */
350*869ffda3Schristos
351*869ffda3Schristos ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
352*869ffda3Schristos arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
353*869ffda3Schristos
354*869ffda3Schristos rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
355*869ffda3Schristos lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
356*869ffda3Schristos
357*869ffda3Schristos k = CTF_K_POINTER; /* Avoid leading whitespace (see below). */
358*869ffda3Schristos
359*869ffda3Schristos for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++)
360*869ffda3Schristos {
361*869ffda3Schristos for (cdp = ctf_list_next (&cd.cd_nodes[prec]);
362*869ffda3Schristos cdp != NULL; cdp = ctf_list_next (cdp))
363*869ffda3Schristos {
364*869ffda3Schristos ctf_file_t *rfp = fp;
365*869ffda3Schristos const ctf_type_t *tp = ctf_lookup_by_id (&rfp, cdp->cd_type);
366*869ffda3Schristos const char *name = ctf_strptr (rfp, tp->ctt_name);
367*869ffda3Schristos
368*869ffda3Schristos if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
369*869ffda3Schristos ctf_decl_sprintf (&cd, " ");
370*869ffda3Schristos
371*869ffda3Schristos if (lp == prec)
372*869ffda3Schristos {
373*869ffda3Schristos ctf_decl_sprintf (&cd, "(");
374*869ffda3Schristos lp = -1;
375*869ffda3Schristos }
376*869ffda3Schristos
377*869ffda3Schristos switch (cdp->cd_kind)
378*869ffda3Schristos {
379*869ffda3Schristos case CTF_K_INTEGER:
380*869ffda3Schristos case CTF_K_FLOAT:
381*869ffda3Schristos case CTF_K_TYPEDEF:
382*869ffda3Schristos ctf_decl_sprintf (&cd, "%s", name);
383*869ffda3Schristos break;
384*869ffda3Schristos case CTF_K_POINTER:
385*869ffda3Schristos ctf_decl_sprintf (&cd, "*");
386*869ffda3Schristos break;
387*869ffda3Schristos case CTF_K_ARRAY:
388*869ffda3Schristos ctf_decl_sprintf (&cd, "[%u]", cdp->cd_n);
389*869ffda3Schristos break;
390*869ffda3Schristos case CTF_K_FUNCTION:
391*869ffda3Schristos ctf_decl_sprintf (&cd, "()");
392*869ffda3Schristos break;
393*869ffda3Schristos case CTF_K_STRUCT:
394*869ffda3Schristos case CTF_K_FORWARD:
395*869ffda3Schristos ctf_decl_sprintf (&cd, "struct %s", name);
396*869ffda3Schristos break;
397*869ffda3Schristos case CTF_K_UNION:
398*869ffda3Schristos ctf_decl_sprintf (&cd, "union %s", name);
399*869ffda3Schristos break;
400*869ffda3Schristos case CTF_K_ENUM:
401*869ffda3Schristos ctf_decl_sprintf (&cd, "enum %s", name);
402*869ffda3Schristos break;
403*869ffda3Schristos case CTF_K_VOLATILE:
404*869ffda3Schristos ctf_decl_sprintf (&cd, "volatile");
405*869ffda3Schristos break;
406*869ffda3Schristos case CTF_K_CONST:
407*869ffda3Schristos ctf_decl_sprintf (&cd, "const");
408*869ffda3Schristos break;
409*869ffda3Schristos case CTF_K_RESTRICT:
410*869ffda3Schristos ctf_decl_sprintf (&cd, "restrict");
411*869ffda3Schristos break;
412*869ffda3Schristos case CTF_K_SLICE:
413*869ffda3Schristos /* No representation: just changes encoding of contained type,
414*869ffda3Schristos which is not in any case printed. Skip it. */
415*869ffda3Schristos break;
416*869ffda3Schristos }
417*869ffda3Schristos
418*869ffda3Schristos k = cdp->cd_kind;
419*869ffda3Schristos }
420*869ffda3Schristos
421*869ffda3Schristos if (rp == prec)
422*869ffda3Schristos ctf_decl_sprintf (&cd, ")");
423*869ffda3Schristos }
424*869ffda3Schristos
425*869ffda3Schristos if (cd.cd_enomem)
426*869ffda3Schristos (void) ctf_set_errno (fp, ENOMEM);
427*869ffda3Schristos
428*869ffda3Schristos buf = ctf_decl_buf (&cd);
429*869ffda3Schristos
430*869ffda3Schristos ctf_decl_fini (&cd);
431*869ffda3Schristos return buf;
432*869ffda3Schristos }
433*869ffda3Schristos
434*869ffda3Schristos /* Lookup the given type ID and print a string name for it into buf. Return
435*869ffda3Schristos the actual number of bytes (not including \0) needed to format the name. */
436*869ffda3Schristos
437*869ffda3Schristos ssize_t
ctf_type_lname(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)438*869ffda3Schristos ctf_type_lname (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
439*869ffda3Schristos {
440*869ffda3Schristos char *str = ctf_type_aname (fp, type);
441*869ffda3Schristos size_t slen;
442*869ffda3Schristos
443*869ffda3Schristos if (str == NULL)
444*869ffda3Schristos return CTF_ERR; /* errno is set for us. */
445*869ffda3Schristos
446*869ffda3Schristos slen = strlen (str);
447*869ffda3Schristos snprintf (buf, len, "%s", str);
448*869ffda3Schristos free (str);
449*869ffda3Schristos
450*869ffda3Schristos if (slen >= len)
451*869ffda3Schristos (void) ctf_set_errno (fp, ECTF_NAMELEN);
452*869ffda3Schristos
453*869ffda3Schristos return slen;
454*869ffda3Schristos }
455*869ffda3Schristos
456*869ffda3Schristos /* Lookup the given type ID and print a string name for it into buf. If buf
457*869ffda3Schristos is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us. */
458*869ffda3Schristos
459*869ffda3Schristos char *
ctf_type_name(ctf_file_t * fp,ctf_id_t type,char * buf,size_t len)460*869ffda3Schristos ctf_type_name (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
461*869ffda3Schristos {
462*869ffda3Schristos ssize_t rv = ctf_type_lname (fp, type, buf, len);
463*869ffda3Schristos return (rv >= 0 && (size_t) rv < len ? buf : NULL);
464*869ffda3Schristos }
465*869ffda3Schristos
466*869ffda3Schristos /* Lookup the given type ID and return its raw, unadorned, undecorated name as a
467*869ffda3Schristos new dynamcally-allocated string. */
468*869ffda3Schristos
469*869ffda3Schristos char *
ctf_type_aname_raw(ctf_file_t * fp,ctf_id_t type)470*869ffda3Schristos ctf_type_aname_raw (ctf_file_t *fp, ctf_id_t type)
471*869ffda3Schristos {
472*869ffda3Schristos const ctf_type_t *tp;
473*869ffda3Schristos
474*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
475*869ffda3Schristos return NULL; /* errno is set for us. */
476*869ffda3Schristos
477*869ffda3Schristos if (ctf_strraw (fp, tp->ctt_name) != NULL)
478*869ffda3Schristos return strdup (ctf_strraw (fp, tp->ctt_name));
479*869ffda3Schristos
480*869ffda3Schristos return NULL;
481*869ffda3Schristos }
482*869ffda3Schristos
483*869ffda3Schristos /* Resolve the type down to a base type node, and then return the size
484*869ffda3Schristos of the type storage in bytes. */
485*869ffda3Schristos
486*869ffda3Schristos ssize_t
ctf_type_size(ctf_file_t * fp,ctf_id_t type)487*869ffda3Schristos ctf_type_size (ctf_file_t *fp, ctf_id_t type)
488*869ffda3Schristos {
489*869ffda3Schristos const ctf_type_t *tp;
490*869ffda3Schristos ssize_t size;
491*869ffda3Schristos ctf_arinfo_t ar;
492*869ffda3Schristos
493*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
494*869ffda3Schristos return -1; /* errno is set for us. */
495*869ffda3Schristos
496*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
497*869ffda3Schristos return -1; /* errno is set for us. */
498*869ffda3Schristos
499*869ffda3Schristos switch (LCTF_INFO_KIND (fp, tp->ctt_info))
500*869ffda3Schristos {
501*869ffda3Schristos case CTF_K_POINTER:
502*869ffda3Schristos return fp->ctf_dmodel->ctd_pointer;
503*869ffda3Schristos
504*869ffda3Schristos case CTF_K_FUNCTION:
505*869ffda3Schristos return 0; /* Function size is only known by symtab. */
506*869ffda3Schristos
507*869ffda3Schristos case CTF_K_ENUM:
508*869ffda3Schristos return fp->ctf_dmodel->ctd_int;
509*869ffda3Schristos
510*869ffda3Schristos case CTF_K_ARRAY:
511*869ffda3Schristos /* ctf_add_array() does not directly encode the element size, but
512*869ffda3Schristos requires the user to multiply to determine the element size.
513*869ffda3Schristos
514*869ffda3Schristos If ctf_get_ctt_size() returns nonzero, then use the recorded
515*869ffda3Schristos size instead. */
516*869ffda3Schristos
517*869ffda3Schristos if ((size = ctf_get_ctt_size (fp, tp, NULL, NULL)) > 0)
518*869ffda3Schristos return size;
519*869ffda3Schristos
520*869ffda3Schristos if (ctf_array_info (fp, type, &ar) < 0
521*869ffda3Schristos || (size = ctf_type_size (fp, ar.ctr_contents)) < 0)
522*869ffda3Schristos return -1; /* errno is set for us. */
523*869ffda3Schristos
524*869ffda3Schristos return size * ar.ctr_nelems;
525*869ffda3Schristos
526*869ffda3Schristos default: /* including slices of enums, etc */
527*869ffda3Schristos return (ctf_get_ctt_size (fp, tp, NULL, NULL));
528*869ffda3Schristos }
529*869ffda3Schristos }
530*869ffda3Schristos
531*869ffda3Schristos /* Resolve the type down to a base type node, and then return the alignment
532*869ffda3Schristos needed for the type storage in bytes.
533*869ffda3Schristos
534*869ffda3Schristos XXX may need arch-dependent attention. */
535*869ffda3Schristos
536*869ffda3Schristos ssize_t
ctf_type_align(ctf_file_t * fp,ctf_id_t type)537*869ffda3Schristos ctf_type_align (ctf_file_t *fp, ctf_id_t type)
538*869ffda3Schristos {
539*869ffda3Schristos const ctf_type_t *tp;
540*869ffda3Schristos ctf_file_t *ofp = fp;
541*869ffda3Schristos int kind;
542*869ffda3Schristos
543*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
544*869ffda3Schristos return -1; /* errno is set for us. */
545*869ffda3Schristos
546*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
547*869ffda3Schristos return -1; /* errno is set for us. */
548*869ffda3Schristos
549*869ffda3Schristos kind = LCTF_INFO_KIND (fp, tp->ctt_info);
550*869ffda3Schristos switch (kind)
551*869ffda3Schristos {
552*869ffda3Schristos case CTF_K_POINTER:
553*869ffda3Schristos case CTF_K_FUNCTION:
554*869ffda3Schristos return fp->ctf_dmodel->ctd_pointer;
555*869ffda3Schristos
556*869ffda3Schristos case CTF_K_ARRAY:
557*869ffda3Schristos {
558*869ffda3Schristos ctf_arinfo_t r;
559*869ffda3Schristos if (ctf_array_info (fp, type, &r) < 0)
560*869ffda3Schristos return -1; /* errno is set for us. */
561*869ffda3Schristos return (ctf_type_align (fp, r.ctr_contents));
562*869ffda3Schristos }
563*869ffda3Schristos
564*869ffda3Schristos case CTF_K_STRUCT:
565*869ffda3Schristos case CTF_K_UNION:
566*869ffda3Schristos {
567*869ffda3Schristos size_t align = 0;
568*869ffda3Schristos ctf_dtdef_t *dtd;
569*869ffda3Schristos
570*869ffda3Schristos if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
571*869ffda3Schristos {
572*869ffda3Schristos uint32_t n = LCTF_INFO_VLEN (fp, tp->ctt_info);
573*869ffda3Schristos ssize_t size, increment;
574*869ffda3Schristos const void *vmp;
575*869ffda3Schristos
576*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, &size, &increment);
577*869ffda3Schristos vmp = (unsigned char *) tp + increment;
578*869ffda3Schristos
579*869ffda3Schristos if (kind == CTF_K_STRUCT)
580*869ffda3Schristos n = MIN (n, 1); /* Only use first member for structs. */
581*869ffda3Schristos
582*869ffda3Schristos if (size < CTF_LSTRUCT_THRESH)
583*869ffda3Schristos {
584*869ffda3Schristos const ctf_member_t *mp = vmp;
585*869ffda3Schristos for (; n != 0; n--, mp++)
586*869ffda3Schristos {
587*869ffda3Schristos ssize_t am = ctf_type_align (fp, mp->ctm_type);
588*869ffda3Schristos align = MAX (align, (size_t) am);
589*869ffda3Schristos }
590*869ffda3Schristos }
591*869ffda3Schristos else
592*869ffda3Schristos {
593*869ffda3Schristos const ctf_lmember_t *lmp = vmp;
594*869ffda3Schristos for (; n != 0; n--, lmp++)
595*869ffda3Schristos {
596*869ffda3Schristos ssize_t am = ctf_type_align (fp, lmp->ctlm_type);
597*869ffda3Schristos align = MAX (align, (size_t) am);
598*869ffda3Schristos }
599*869ffda3Schristos }
600*869ffda3Schristos }
601*869ffda3Schristos else
602*869ffda3Schristos {
603*869ffda3Schristos ctf_dmdef_t *dmd;
604*869ffda3Schristos
605*869ffda3Schristos for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
606*869ffda3Schristos dmd != NULL; dmd = ctf_list_next (dmd))
607*869ffda3Schristos {
608*869ffda3Schristos ssize_t am = ctf_type_align (fp, dmd->dmd_type);
609*869ffda3Schristos align = MAX (align, (size_t) am);
610*869ffda3Schristos if (kind == CTF_K_STRUCT)
611*869ffda3Schristos break;
612*869ffda3Schristos }
613*869ffda3Schristos }
614*869ffda3Schristos
615*869ffda3Schristos return align;
616*869ffda3Schristos }
617*869ffda3Schristos
618*869ffda3Schristos case CTF_K_ENUM:
619*869ffda3Schristos return fp->ctf_dmodel->ctd_int;
620*869ffda3Schristos
621*869ffda3Schristos default: /* including slices of enums, etc */
622*869ffda3Schristos return (ctf_get_ctt_size (fp, tp, NULL, NULL));
623*869ffda3Schristos }
624*869ffda3Schristos }
625*869ffda3Schristos
626*869ffda3Schristos /* Return the kind (CTF_K_* constant) for the specified type ID. */
627*869ffda3Schristos
628*869ffda3Schristos int
ctf_type_kind_unsliced(ctf_file_t * fp,ctf_id_t type)629*869ffda3Schristos ctf_type_kind_unsliced (ctf_file_t *fp, ctf_id_t type)
630*869ffda3Schristos {
631*869ffda3Schristos const ctf_type_t *tp;
632*869ffda3Schristos
633*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
634*869ffda3Schristos return -1; /* errno is set for us. */
635*869ffda3Schristos
636*869ffda3Schristos return (LCTF_INFO_KIND (fp, tp->ctt_info));
637*869ffda3Schristos }
638*869ffda3Schristos
639*869ffda3Schristos /* Return the kind (CTF_K_* constant) for the specified type ID.
640*869ffda3Schristos Slices are considered to be of the same kind as the type sliced. */
641*869ffda3Schristos
642*869ffda3Schristos int
ctf_type_kind(ctf_file_t * fp,ctf_id_t type)643*869ffda3Schristos ctf_type_kind (ctf_file_t *fp, ctf_id_t type)
644*869ffda3Schristos {
645*869ffda3Schristos int kind;
646*869ffda3Schristos
647*869ffda3Schristos if ((kind = ctf_type_kind_unsliced (fp, type)) < 0)
648*869ffda3Schristos return -1;
649*869ffda3Schristos
650*869ffda3Schristos if (kind == CTF_K_SLICE)
651*869ffda3Schristos {
652*869ffda3Schristos if ((type = ctf_type_reference (fp, type)) == CTF_ERR)
653*869ffda3Schristos return -1;
654*869ffda3Schristos kind = ctf_type_kind_unsliced (fp, type);
655*869ffda3Schristos }
656*869ffda3Schristos
657*869ffda3Schristos return kind;
658*869ffda3Schristos }
659*869ffda3Schristos
660*869ffda3Schristos /* If the type is one that directly references another type (such as POINTER),
661*869ffda3Schristos then return the ID of the type to which it refers. */
662*869ffda3Schristos
663*869ffda3Schristos ctf_id_t
ctf_type_reference(ctf_file_t * fp,ctf_id_t type)664*869ffda3Schristos ctf_type_reference (ctf_file_t *fp, ctf_id_t type)
665*869ffda3Schristos {
666*869ffda3Schristos ctf_file_t *ofp = fp;
667*869ffda3Schristos const ctf_type_t *tp;
668*869ffda3Schristos
669*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
670*869ffda3Schristos return CTF_ERR; /* errno is set for us. */
671*869ffda3Schristos
672*869ffda3Schristos switch (LCTF_INFO_KIND (fp, tp->ctt_info))
673*869ffda3Schristos {
674*869ffda3Schristos case CTF_K_POINTER:
675*869ffda3Schristos case CTF_K_TYPEDEF:
676*869ffda3Schristos case CTF_K_VOLATILE:
677*869ffda3Schristos case CTF_K_CONST:
678*869ffda3Schristos case CTF_K_RESTRICT:
679*869ffda3Schristos return tp->ctt_type;
680*869ffda3Schristos /* Slices store their type in an unusual place. */
681*869ffda3Schristos case CTF_K_SLICE:
682*869ffda3Schristos {
683*869ffda3Schristos const ctf_slice_t *sp;
684*869ffda3Schristos ssize_t increment;
685*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
686*869ffda3Schristos sp = (const ctf_slice_t *) ((uintptr_t) tp + increment);
687*869ffda3Schristos return sp->cts_type;
688*869ffda3Schristos }
689*869ffda3Schristos default:
690*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTREF));
691*869ffda3Schristos }
692*869ffda3Schristos }
693*869ffda3Schristos
694*869ffda3Schristos /* Find a pointer to type by looking in fp->ctf_ptrtab. If we can't find a
695*869ffda3Schristos pointer to the given type, see if we can compute a pointer to the type
696*869ffda3Schristos resulting from resolving the type down to its base type and use that
697*869ffda3Schristos instead. This helps with cases where the CTF data includes "struct foo *"
698*869ffda3Schristos but not "foo_t *" and the user accesses "foo_t *" in the debugger.
699*869ffda3Schristos
700*869ffda3Schristos XXX what about parent containers? */
701*869ffda3Schristos
702*869ffda3Schristos ctf_id_t
ctf_type_pointer(ctf_file_t * fp,ctf_id_t type)703*869ffda3Schristos ctf_type_pointer (ctf_file_t *fp, ctf_id_t type)
704*869ffda3Schristos {
705*869ffda3Schristos ctf_file_t *ofp = fp;
706*869ffda3Schristos ctf_id_t ntype;
707*869ffda3Schristos
708*869ffda3Schristos if (ctf_lookup_by_id (&fp, type) == NULL)
709*869ffda3Schristos return CTF_ERR; /* errno is set for us. */
710*869ffda3Schristos
711*869ffda3Schristos if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)]) != 0)
712*869ffda3Schristos return (LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
713*869ffda3Schristos
714*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
715*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTYPE));
716*869ffda3Schristos
717*869ffda3Schristos if (ctf_lookup_by_id (&fp, type) == NULL)
718*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTYPE));
719*869ffda3Schristos
720*869ffda3Schristos if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)]) != 0)
721*869ffda3Schristos return (LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
722*869ffda3Schristos
723*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTYPE));
724*869ffda3Schristos }
725*869ffda3Schristos
726*869ffda3Schristos /* Return the encoding for the specified INTEGER or FLOAT. */
727*869ffda3Schristos
728*869ffda3Schristos int
ctf_type_encoding(ctf_file_t * fp,ctf_id_t type,ctf_encoding_t * ep)729*869ffda3Schristos ctf_type_encoding (ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
730*869ffda3Schristos {
731*869ffda3Schristos ctf_file_t *ofp = fp;
732*869ffda3Schristos ctf_dtdef_t *dtd;
733*869ffda3Schristos const ctf_type_t *tp;
734*869ffda3Schristos ssize_t increment;
735*869ffda3Schristos uint32_t data;
736*869ffda3Schristos
737*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
738*869ffda3Schristos return -1; /* errno is set for us. */
739*869ffda3Schristos
740*869ffda3Schristos if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
741*869ffda3Schristos {
742*869ffda3Schristos switch (LCTF_INFO_KIND (fp, tp->ctt_info))
743*869ffda3Schristos {
744*869ffda3Schristos case CTF_K_INTEGER:
745*869ffda3Schristos case CTF_K_FLOAT:
746*869ffda3Schristos *ep = dtd->dtd_u.dtu_enc;
747*869ffda3Schristos break;
748*869ffda3Schristos case CTF_K_SLICE:
749*869ffda3Schristos {
750*869ffda3Schristos const ctf_slice_t *slice;
751*869ffda3Schristos ctf_encoding_t underlying_en;
752*869ffda3Schristos slice = &dtd->dtd_u.dtu_slice;
753*869ffda3Schristos
754*869ffda3Schristos data = ctf_type_encoding (fp, slice->cts_type, &underlying_en);
755*869ffda3Schristos ep->cte_format = underlying_en.cte_format;
756*869ffda3Schristos ep->cte_offset = slice->cts_offset;
757*869ffda3Schristos ep->cte_bits = slice->cts_bits;
758*869ffda3Schristos break;
759*869ffda3Schristos }
760*869ffda3Schristos default:
761*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTINTFP));
762*869ffda3Schristos }
763*869ffda3Schristos return 0;
764*869ffda3Schristos }
765*869ffda3Schristos
766*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
767*869ffda3Schristos
768*869ffda3Schristos switch (LCTF_INFO_KIND (fp, tp->ctt_info))
769*869ffda3Schristos {
770*869ffda3Schristos case CTF_K_INTEGER:
771*869ffda3Schristos data = *(const uint32_t *) ((uintptr_t) tp + increment);
772*869ffda3Schristos ep->cte_format = CTF_INT_ENCODING (data);
773*869ffda3Schristos ep->cte_offset = CTF_INT_OFFSET (data);
774*869ffda3Schristos ep->cte_bits = CTF_INT_BITS (data);
775*869ffda3Schristos break;
776*869ffda3Schristos case CTF_K_FLOAT:
777*869ffda3Schristos data = *(const uint32_t *) ((uintptr_t) tp + increment);
778*869ffda3Schristos ep->cte_format = CTF_FP_ENCODING (data);
779*869ffda3Schristos ep->cte_offset = CTF_FP_OFFSET (data);
780*869ffda3Schristos ep->cte_bits = CTF_FP_BITS (data);
781*869ffda3Schristos break;
782*869ffda3Schristos case CTF_K_SLICE:
783*869ffda3Schristos {
784*869ffda3Schristos const ctf_slice_t *slice;
785*869ffda3Schristos ctf_encoding_t underlying_en;
786*869ffda3Schristos
787*869ffda3Schristos slice = (ctf_slice_t *) ((uintptr_t) tp + increment);
788*869ffda3Schristos data = ctf_type_encoding (fp, slice->cts_type, &underlying_en);
789*869ffda3Schristos
790*869ffda3Schristos ep->cte_format = underlying_en.cte_format;
791*869ffda3Schristos ep->cte_offset = slice->cts_offset;
792*869ffda3Schristos ep->cte_bits = slice->cts_bits;
793*869ffda3Schristos break;
794*869ffda3Schristos }
795*869ffda3Schristos default:
796*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTINTFP));
797*869ffda3Schristos }
798*869ffda3Schristos
799*869ffda3Schristos return 0;
800*869ffda3Schristos }
801*869ffda3Schristos
802*869ffda3Schristos int
ctf_type_cmp(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)803*869ffda3Schristos ctf_type_cmp (ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp,
804*869ffda3Schristos ctf_id_t rtype)
805*869ffda3Schristos {
806*869ffda3Schristos int rval;
807*869ffda3Schristos
808*869ffda3Schristos if (ltype < rtype)
809*869ffda3Schristos rval = -1;
810*869ffda3Schristos else if (ltype > rtype)
811*869ffda3Schristos rval = 1;
812*869ffda3Schristos else
813*869ffda3Schristos rval = 0;
814*869ffda3Schristos
815*869ffda3Schristos if (lfp == rfp)
816*869ffda3Schristos return rval;
817*869ffda3Schristos
818*869ffda3Schristos if (LCTF_TYPE_ISPARENT (lfp, ltype) && lfp->ctf_parent != NULL)
819*869ffda3Schristos lfp = lfp->ctf_parent;
820*869ffda3Schristos
821*869ffda3Schristos if (LCTF_TYPE_ISPARENT (rfp, rtype) && rfp->ctf_parent != NULL)
822*869ffda3Schristos rfp = rfp->ctf_parent;
823*869ffda3Schristos
824*869ffda3Schristos if (lfp < rfp)
825*869ffda3Schristos return -1;
826*869ffda3Schristos
827*869ffda3Schristos if (lfp > rfp)
828*869ffda3Schristos return 1;
829*869ffda3Schristos
830*869ffda3Schristos return rval;
831*869ffda3Schristos }
832*869ffda3Schristos
833*869ffda3Schristos /* Return a boolean value indicating if two types are compatible. This function
834*869ffda3Schristos returns true if the two types are the same, or if they (or their ultimate
835*869ffda3Schristos base type) have the same encoding properties, or (for structs / unions /
836*869ffda3Schristos enums / forward declarations) if they have the same name and (for structs /
837*869ffda3Schristos unions) member count. */
838*869ffda3Schristos
839*869ffda3Schristos int
ctf_type_compat(ctf_file_t * lfp,ctf_id_t ltype,ctf_file_t * rfp,ctf_id_t rtype)840*869ffda3Schristos ctf_type_compat (ctf_file_t *lfp, ctf_id_t ltype,
841*869ffda3Schristos ctf_file_t *rfp, ctf_id_t rtype)
842*869ffda3Schristos {
843*869ffda3Schristos const ctf_type_t *ltp, *rtp;
844*869ffda3Schristos ctf_encoding_t le, re;
845*869ffda3Schristos ctf_arinfo_t la, ra;
846*869ffda3Schristos uint32_t lkind, rkind;
847*869ffda3Schristos int same_names = 0;
848*869ffda3Schristos
849*869ffda3Schristos if (ctf_type_cmp (lfp, ltype, rfp, rtype) == 0)
850*869ffda3Schristos return 1;
851*869ffda3Schristos
852*869ffda3Schristos ltype = ctf_type_resolve (lfp, ltype);
853*869ffda3Schristos lkind = ctf_type_kind (lfp, ltype);
854*869ffda3Schristos
855*869ffda3Schristos rtype = ctf_type_resolve (rfp, rtype);
856*869ffda3Schristos rkind = ctf_type_kind (rfp, rtype);
857*869ffda3Schristos
858*869ffda3Schristos ltp = ctf_lookup_by_id (&lfp, ltype);
859*869ffda3Schristos rtp = ctf_lookup_by_id (&rfp, rtype);
860*869ffda3Schristos
861*869ffda3Schristos if (ltp != NULL && rtp != NULL)
862*869ffda3Schristos same_names = (strcmp (ctf_strptr (lfp, ltp->ctt_name),
863*869ffda3Schristos ctf_strptr (rfp, rtp->ctt_name)) == 0);
864*869ffda3Schristos
865*869ffda3Schristos if (((lkind == CTF_K_ENUM) && (rkind == CTF_K_INTEGER)) ||
866*869ffda3Schristos ((rkind == CTF_K_ENUM) && (lkind == CTF_K_INTEGER)))
867*869ffda3Schristos return 1;
868*869ffda3Schristos
869*869ffda3Schristos if (lkind != rkind)
870*869ffda3Schristos return 0;
871*869ffda3Schristos
872*869ffda3Schristos switch (lkind)
873*869ffda3Schristos {
874*869ffda3Schristos case CTF_K_INTEGER:
875*869ffda3Schristos case CTF_K_FLOAT:
876*869ffda3Schristos memset (&le, 0, sizeof (le));
877*869ffda3Schristos memset (&re, 0, sizeof (re));
878*869ffda3Schristos return (ctf_type_encoding (lfp, ltype, &le) == 0
879*869ffda3Schristos && ctf_type_encoding (rfp, rtype, &re) == 0
880*869ffda3Schristos && memcmp (&le, &re, sizeof (ctf_encoding_t)) == 0);
881*869ffda3Schristos case CTF_K_POINTER:
882*869ffda3Schristos return (ctf_type_compat (lfp, ctf_type_reference (lfp, ltype),
883*869ffda3Schristos rfp, ctf_type_reference (rfp, rtype)));
884*869ffda3Schristos case CTF_K_ARRAY:
885*869ffda3Schristos return (ctf_array_info (lfp, ltype, &la) == 0
886*869ffda3Schristos && ctf_array_info (rfp, rtype, &ra) == 0
887*869ffda3Schristos && la.ctr_nelems == ra.ctr_nelems
888*869ffda3Schristos && ctf_type_compat (lfp, la.ctr_contents, rfp, ra.ctr_contents)
889*869ffda3Schristos && ctf_type_compat (lfp, la.ctr_index, rfp, ra.ctr_index));
890*869ffda3Schristos case CTF_K_STRUCT:
891*869ffda3Schristos case CTF_K_UNION:
892*869ffda3Schristos return (same_names && (ctf_type_size (lfp, ltype)
893*869ffda3Schristos == ctf_type_size (rfp, rtype)));
894*869ffda3Schristos case CTF_K_ENUM:
895*869ffda3Schristos {
896*869ffda3Schristos int lencoded, rencoded;
897*869ffda3Schristos lencoded = ctf_type_encoding (lfp, ltype, &le);
898*869ffda3Schristos rencoded = ctf_type_encoding (rfp, rtype, &re);
899*869ffda3Schristos
900*869ffda3Schristos if ((lencoded != rencoded) ||
901*869ffda3Schristos ((lencoded == 0) && memcmp (&le, &re, sizeof (ctf_encoding_t)) != 0))
902*869ffda3Schristos return 0;
903*869ffda3Schristos }
904*869ffda3Schristos /* FALLTHRU */
905*869ffda3Schristos case CTF_K_FORWARD:
906*869ffda3Schristos return same_names; /* No other checks required for these type kinds. */
907*869ffda3Schristos default:
908*869ffda3Schristos return 0; /* Should not get here since we did a resolve. */
909*869ffda3Schristos }
910*869ffda3Schristos }
911*869ffda3Schristos
912*869ffda3Schristos /* Return the type and offset for a given member of a STRUCT or UNION. */
913*869ffda3Schristos
914*869ffda3Schristos int
ctf_member_info(ctf_file_t * fp,ctf_id_t type,const char * name,ctf_membinfo_t * mip)915*869ffda3Schristos ctf_member_info (ctf_file_t *fp, ctf_id_t type, const char *name,
916*869ffda3Schristos ctf_membinfo_t *mip)
917*869ffda3Schristos {
918*869ffda3Schristos ctf_file_t *ofp = fp;
919*869ffda3Schristos const ctf_type_t *tp;
920*869ffda3Schristos ctf_dtdef_t *dtd;
921*869ffda3Schristos ssize_t size, increment;
922*869ffda3Schristos uint32_t kind, n;
923*869ffda3Schristos
924*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
925*869ffda3Schristos return -1; /* errno is set for us. */
926*869ffda3Schristos
927*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
928*869ffda3Schristos return -1; /* errno is set for us. */
929*869ffda3Schristos
930*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, &size, &increment);
931*869ffda3Schristos kind = LCTF_INFO_KIND (fp, tp->ctt_info);
932*869ffda3Schristos
933*869ffda3Schristos if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
934*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTSOU));
935*869ffda3Schristos
936*869ffda3Schristos if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
937*869ffda3Schristos {
938*869ffda3Schristos if (size < CTF_LSTRUCT_THRESH)
939*869ffda3Schristos {
940*869ffda3Schristos const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
941*869ffda3Schristos increment);
942*869ffda3Schristos
943*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
944*869ffda3Schristos {
945*869ffda3Schristos if (strcmp (ctf_strptr (fp, mp->ctm_name), name) == 0)
946*869ffda3Schristos {
947*869ffda3Schristos mip->ctm_type = mp->ctm_type;
948*869ffda3Schristos mip->ctm_offset = mp->ctm_offset;
949*869ffda3Schristos return 0;
950*869ffda3Schristos }
951*869ffda3Schristos }
952*869ffda3Schristos }
953*869ffda3Schristos else
954*869ffda3Schristos {
955*869ffda3Schristos const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
956*869ffda3Schristos increment);
957*869ffda3Schristos
958*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
959*869ffda3Schristos {
960*869ffda3Schristos if (strcmp (ctf_strptr (fp, lmp->ctlm_name), name) == 0)
961*869ffda3Schristos {
962*869ffda3Schristos mip->ctm_type = lmp->ctlm_type;
963*869ffda3Schristos mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp);
964*869ffda3Schristos return 0;
965*869ffda3Schristos }
966*869ffda3Schristos }
967*869ffda3Schristos }
968*869ffda3Schristos }
969*869ffda3Schristos else
970*869ffda3Schristos {
971*869ffda3Schristos ctf_dmdef_t *dmd;
972*869ffda3Schristos
973*869ffda3Schristos for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
974*869ffda3Schristos dmd != NULL; dmd = ctf_list_next (dmd))
975*869ffda3Schristos {
976*869ffda3Schristos if (strcmp (dmd->dmd_name, name) == 0)
977*869ffda3Schristos {
978*869ffda3Schristos mip->ctm_type = dmd->dmd_type;
979*869ffda3Schristos mip->ctm_offset = dmd->dmd_offset;
980*869ffda3Schristos return 0;
981*869ffda3Schristos }
982*869ffda3Schristos }
983*869ffda3Schristos }
984*869ffda3Schristos
985*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOMEMBNAM));
986*869ffda3Schristos }
987*869ffda3Schristos
988*869ffda3Schristos /* Return the array type, index, and size information for the specified ARRAY. */
989*869ffda3Schristos
990*869ffda3Schristos int
ctf_array_info(ctf_file_t * fp,ctf_id_t type,ctf_arinfo_t * arp)991*869ffda3Schristos ctf_array_info (ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
992*869ffda3Schristos {
993*869ffda3Schristos ctf_file_t *ofp = fp;
994*869ffda3Schristos const ctf_type_t *tp;
995*869ffda3Schristos const ctf_array_t *ap;
996*869ffda3Schristos const ctf_dtdef_t *dtd;
997*869ffda3Schristos ssize_t increment;
998*869ffda3Schristos
999*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1000*869ffda3Schristos return -1; /* errno is set for us. */
1001*869ffda3Schristos
1002*869ffda3Schristos if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ARRAY)
1003*869ffda3Schristos return (ctf_set_errno (ofp, ECTF_NOTARRAY));
1004*869ffda3Schristos
1005*869ffda3Schristos if ((dtd = ctf_dynamic_type (ofp, type)) != NULL)
1006*869ffda3Schristos {
1007*869ffda3Schristos *arp = dtd->dtd_u.dtu_arr;
1008*869ffda3Schristos return 0;
1009*869ffda3Schristos }
1010*869ffda3Schristos
1011*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
1012*869ffda3Schristos
1013*869ffda3Schristos ap = (const ctf_array_t *) ((uintptr_t) tp + increment);
1014*869ffda3Schristos arp->ctr_contents = ap->cta_contents;
1015*869ffda3Schristos arp->ctr_index = ap->cta_index;
1016*869ffda3Schristos arp->ctr_nelems = ap->cta_nelems;
1017*869ffda3Schristos
1018*869ffda3Schristos return 0;
1019*869ffda3Schristos }
1020*869ffda3Schristos
1021*869ffda3Schristos /* Convert the specified value to the corresponding enum tag name, if a
1022*869ffda3Schristos matching name can be found. Otherwise NULL is returned. */
1023*869ffda3Schristos
1024*869ffda3Schristos const char *
ctf_enum_name(ctf_file_t * fp,ctf_id_t type,int value)1025*869ffda3Schristos ctf_enum_name (ctf_file_t *fp, ctf_id_t type, int value)
1026*869ffda3Schristos {
1027*869ffda3Schristos ctf_file_t *ofp = fp;
1028*869ffda3Schristos const ctf_type_t *tp;
1029*869ffda3Schristos const ctf_enum_t *ep;
1030*869ffda3Schristos const ctf_dtdef_t *dtd;
1031*869ffda3Schristos ssize_t increment;
1032*869ffda3Schristos uint32_t n;
1033*869ffda3Schristos
1034*869ffda3Schristos if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
1035*869ffda3Schristos return NULL; /* errno is set for us. */
1036*869ffda3Schristos
1037*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1038*869ffda3Schristos return NULL; /* errno is set for us. */
1039*869ffda3Schristos
1040*869ffda3Schristos if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
1041*869ffda3Schristos {
1042*869ffda3Schristos (void) ctf_set_errno (ofp, ECTF_NOTENUM);
1043*869ffda3Schristos return NULL;
1044*869ffda3Schristos }
1045*869ffda3Schristos
1046*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
1047*869ffda3Schristos
1048*869ffda3Schristos if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
1049*869ffda3Schristos {
1050*869ffda3Schristos ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
1051*869ffda3Schristos
1052*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
1053*869ffda3Schristos {
1054*869ffda3Schristos if (ep->cte_value == value)
1055*869ffda3Schristos return (ctf_strptr (fp, ep->cte_name));
1056*869ffda3Schristos }
1057*869ffda3Schristos }
1058*869ffda3Schristos else
1059*869ffda3Schristos {
1060*869ffda3Schristos ctf_dmdef_t *dmd;
1061*869ffda3Schristos
1062*869ffda3Schristos for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
1063*869ffda3Schristos dmd != NULL; dmd = ctf_list_next (dmd))
1064*869ffda3Schristos {
1065*869ffda3Schristos if (dmd->dmd_value == value)
1066*869ffda3Schristos return dmd->dmd_name;
1067*869ffda3Schristos }
1068*869ffda3Schristos }
1069*869ffda3Schristos
1070*869ffda3Schristos (void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
1071*869ffda3Schristos return NULL;
1072*869ffda3Schristos }
1073*869ffda3Schristos
1074*869ffda3Schristos /* Convert the specified enum tag name to the corresponding value, if a
1075*869ffda3Schristos matching name can be found. Otherwise CTF_ERR is returned. */
1076*869ffda3Schristos
1077*869ffda3Schristos int
ctf_enum_value(ctf_file_t * fp,ctf_id_t type,const char * name,int * valp)1078*869ffda3Schristos ctf_enum_value (ctf_file_t * fp, ctf_id_t type, const char *name, int *valp)
1079*869ffda3Schristos {
1080*869ffda3Schristos ctf_file_t *ofp = fp;
1081*869ffda3Schristos const ctf_type_t *tp;
1082*869ffda3Schristos const ctf_enum_t *ep;
1083*869ffda3Schristos const ctf_dtdef_t *dtd;
1084*869ffda3Schristos ssize_t increment;
1085*869ffda3Schristos uint32_t n;
1086*869ffda3Schristos
1087*869ffda3Schristos if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR)
1088*869ffda3Schristos return -1; /* errno is set for us. */
1089*869ffda3Schristos
1090*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1091*869ffda3Schristos return -1; /* errno is set for us. */
1092*869ffda3Schristos
1093*869ffda3Schristos if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM)
1094*869ffda3Schristos {
1095*869ffda3Schristos (void) ctf_set_errno (ofp, ECTF_NOTENUM);
1096*869ffda3Schristos return -1;
1097*869ffda3Schristos }
1098*869ffda3Schristos
1099*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, NULL, &increment);
1100*869ffda3Schristos
1101*869ffda3Schristos ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
1102*869ffda3Schristos
1103*869ffda3Schristos if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
1104*869ffda3Schristos {
1105*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
1106*869ffda3Schristos {
1107*869ffda3Schristos if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0)
1108*869ffda3Schristos {
1109*869ffda3Schristos if (valp != NULL)
1110*869ffda3Schristos *valp = ep->cte_value;
1111*869ffda3Schristos return 0;
1112*869ffda3Schristos }
1113*869ffda3Schristos }
1114*869ffda3Schristos }
1115*869ffda3Schristos else
1116*869ffda3Schristos {
1117*869ffda3Schristos ctf_dmdef_t *dmd;
1118*869ffda3Schristos
1119*869ffda3Schristos for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
1120*869ffda3Schristos dmd != NULL; dmd = ctf_list_next (dmd))
1121*869ffda3Schristos {
1122*869ffda3Schristos if (strcmp (dmd->dmd_name, name) == 0)
1123*869ffda3Schristos {
1124*869ffda3Schristos if (valp != NULL)
1125*869ffda3Schristos *valp = dmd->dmd_value;
1126*869ffda3Schristos return 0;
1127*869ffda3Schristos }
1128*869ffda3Schristos }
1129*869ffda3Schristos }
1130*869ffda3Schristos
1131*869ffda3Schristos (void) ctf_set_errno (ofp, ECTF_NOENUMNAM);
1132*869ffda3Schristos return -1;
1133*869ffda3Schristos }
1134*869ffda3Schristos
1135*869ffda3Schristos /* Given a type ID relating to a function type, return info on return types and
1136*869ffda3Schristos arg counts for that function. */
1137*869ffda3Schristos
1138*869ffda3Schristos int
ctf_func_type_info(ctf_file_t * fp,ctf_id_t type,ctf_funcinfo_t * fip)1139*869ffda3Schristos ctf_func_type_info (ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
1140*869ffda3Schristos {
1141*869ffda3Schristos const ctf_type_t *tp;
1142*869ffda3Schristos uint32_t kind;
1143*869ffda3Schristos const uint32_t *args;
1144*869ffda3Schristos const ctf_dtdef_t *dtd;
1145*869ffda3Schristos ssize_t size, increment;
1146*869ffda3Schristos
1147*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
1148*869ffda3Schristos return -1; /* errno is set for us. */
1149*869ffda3Schristos
1150*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1151*869ffda3Schristos return -1; /* errno is set for us. */
1152*869ffda3Schristos
1153*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, &size, &increment);
1154*869ffda3Schristos kind = LCTF_INFO_KIND (fp, tp->ctt_info);
1155*869ffda3Schristos
1156*869ffda3Schristos if (kind != CTF_K_FUNCTION)
1157*869ffda3Schristos return (ctf_set_errno (fp, ECTF_NOTFUNC));
1158*869ffda3Schristos
1159*869ffda3Schristos fip->ctc_return = tp->ctt_type;
1160*869ffda3Schristos fip->ctc_flags = 0;
1161*869ffda3Schristos fip->ctc_argc = LCTF_INFO_VLEN (fp, tp->ctt_info);
1162*869ffda3Schristos
1163*869ffda3Schristos if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
1164*869ffda3Schristos args = (uint32_t *) ((uintptr_t) tp + increment);
1165*869ffda3Schristos else
1166*869ffda3Schristos args = (uint32_t *) dtd->dtd_u.dtu_argv;
1167*869ffda3Schristos
1168*869ffda3Schristos if (fip->ctc_argc != 0 && args[fip->ctc_argc - 1] == 0)
1169*869ffda3Schristos {
1170*869ffda3Schristos fip->ctc_flags |= CTF_FUNC_VARARG;
1171*869ffda3Schristos fip->ctc_argc--;
1172*869ffda3Schristos }
1173*869ffda3Schristos
1174*869ffda3Schristos return 0;
1175*869ffda3Schristos }
1176*869ffda3Schristos
1177*869ffda3Schristos /* Given a type ID relating to a function type,, return the arguments for the
1178*869ffda3Schristos function. */
1179*869ffda3Schristos
1180*869ffda3Schristos int
ctf_func_type_args(ctf_file_t * fp,ctf_id_t type,uint32_t argc,ctf_id_t * argv)1181*869ffda3Schristos ctf_func_type_args (ctf_file_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv)
1182*869ffda3Schristos {
1183*869ffda3Schristos const ctf_type_t *tp;
1184*869ffda3Schristos const uint32_t *args;
1185*869ffda3Schristos const ctf_dtdef_t *dtd;
1186*869ffda3Schristos ssize_t size, increment;
1187*869ffda3Schristos ctf_funcinfo_t f;
1188*869ffda3Schristos
1189*869ffda3Schristos if (ctf_func_type_info (fp, type, &f) < 0)
1190*869ffda3Schristos return -1; /* errno is set for us. */
1191*869ffda3Schristos
1192*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
1193*869ffda3Schristos return -1; /* errno is set for us. */
1194*869ffda3Schristos
1195*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1196*869ffda3Schristos return -1; /* errno is set for us. */
1197*869ffda3Schristos
1198*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, &size, &increment);
1199*869ffda3Schristos
1200*869ffda3Schristos if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
1201*869ffda3Schristos args = (uint32_t *) ((uintptr_t) tp + increment);
1202*869ffda3Schristos else
1203*869ffda3Schristos args = (uint32_t *) dtd->dtd_u.dtu_argv;
1204*869ffda3Schristos
1205*869ffda3Schristos for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
1206*869ffda3Schristos *argv++ = *args++;
1207*869ffda3Schristos
1208*869ffda3Schristos return 0;
1209*869ffda3Schristos }
1210*869ffda3Schristos
1211*869ffda3Schristos /* Recursively visit the members of any type. This function is used as the
1212*869ffda3Schristos engine for ctf_type_visit, below. We resolve the input type, recursively
1213*869ffda3Schristos invoke ourself for each type member if the type is a struct or union, and
1214*869ffda3Schristos then invoke the callback function on the current type. If any callback
1215*869ffda3Schristos returns non-zero, we abort and percolate the error code back up to the top. */
1216*869ffda3Schristos
1217*869ffda3Schristos static int
ctf_type_rvisit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg,const char * name,unsigned long offset,int depth)1218*869ffda3Schristos ctf_type_rvisit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func,
1219*869ffda3Schristos void *arg, const char *name, unsigned long offset, int depth)
1220*869ffda3Schristos {
1221*869ffda3Schristos ctf_id_t otype = type;
1222*869ffda3Schristos const ctf_type_t *tp;
1223*869ffda3Schristos const ctf_dtdef_t *dtd;
1224*869ffda3Schristos ssize_t size, increment;
1225*869ffda3Schristos uint32_t kind, n;
1226*869ffda3Schristos int rc;
1227*869ffda3Schristos
1228*869ffda3Schristos if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
1229*869ffda3Schristos return -1; /* errno is set for us. */
1230*869ffda3Schristos
1231*869ffda3Schristos if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
1232*869ffda3Schristos return -1; /* errno is set for us. */
1233*869ffda3Schristos
1234*869ffda3Schristos if ((rc = func (name, otype, offset, depth, arg)) != 0)
1235*869ffda3Schristos return rc;
1236*869ffda3Schristos
1237*869ffda3Schristos kind = LCTF_INFO_KIND (fp, tp->ctt_info);
1238*869ffda3Schristos
1239*869ffda3Schristos if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
1240*869ffda3Schristos return 0;
1241*869ffda3Schristos
1242*869ffda3Schristos (void) ctf_get_ctt_size (fp, tp, &size, &increment);
1243*869ffda3Schristos
1244*869ffda3Schristos if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
1245*869ffda3Schristos {
1246*869ffda3Schristos if (size < CTF_LSTRUCT_THRESH)
1247*869ffda3Schristos {
1248*869ffda3Schristos const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp +
1249*869ffda3Schristos increment);
1250*869ffda3Schristos
1251*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++)
1252*869ffda3Schristos {
1253*869ffda3Schristos if ((rc = ctf_type_rvisit (fp, mp->ctm_type,
1254*869ffda3Schristos func, arg, ctf_strptr (fp,
1255*869ffda3Schristos mp->ctm_name),
1256*869ffda3Schristos offset + mp->ctm_offset,
1257*869ffda3Schristos depth + 1)) != 0)
1258*869ffda3Schristos return rc;
1259*869ffda3Schristos }
1260*869ffda3Schristos }
1261*869ffda3Schristos else
1262*869ffda3Schristos {
1263*869ffda3Schristos const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp +
1264*869ffda3Schristos increment);
1265*869ffda3Schristos
1266*869ffda3Schristos for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++)
1267*869ffda3Schristos {
1268*869ffda3Schristos if ((rc = ctf_type_rvisit (fp, lmp->ctlm_type,
1269*869ffda3Schristos func, arg, ctf_strptr (fp,
1270*869ffda3Schristos lmp->ctlm_name),
1271*869ffda3Schristos offset + (unsigned long) CTF_LMEM_OFFSET (lmp),
1272*869ffda3Schristos depth + 1)) != 0)
1273*869ffda3Schristos return rc;
1274*869ffda3Schristos }
1275*869ffda3Schristos }
1276*869ffda3Schristos }
1277*869ffda3Schristos else
1278*869ffda3Schristos {
1279*869ffda3Schristos ctf_dmdef_t *dmd;
1280*869ffda3Schristos
1281*869ffda3Schristos for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
1282*869ffda3Schristos dmd != NULL; dmd = ctf_list_next (dmd))
1283*869ffda3Schristos {
1284*869ffda3Schristos if ((rc = ctf_type_rvisit (fp, dmd->dmd_type, func, arg,
1285*869ffda3Schristos dmd->dmd_name, dmd->dmd_offset,
1286*869ffda3Schristos depth + 1)) != 0)
1287*869ffda3Schristos return rc;
1288*869ffda3Schristos }
1289*869ffda3Schristos }
1290*869ffda3Schristos
1291*869ffda3Schristos return 0;
1292*869ffda3Schristos }
1293*869ffda3Schristos
1294*869ffda3Schristos /* Recursively visit the members of any type. We pass the name, member
1295*869ffda3Schristos type, and offset of each member to the specified callback function. */
1296*869ffda3Schristos int
ctf_type_visit(ctf_file_t * fp,ctf_id_t type,ctf_visit_f * func,void * arg)1297*869ffda3Schristos ctf_type_visit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
1298*869ffda3Schristos {
1299*869ffda3Schristos return (ctf_type_rvisit (fp, type, func, arg, "", 0, 0));
1300*869ffda3Schristos }
1301