xref: /dflybsd-src/contrib/binutils-2.34/libctf/ctf-types.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
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