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