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