xref: /netbsd-src/external/gpl3/gdb/dist/libctf/ctf-lookup.c (revision 4439cfd0acf9c7dc90625e5cd83b2317a9ab8967)
1 /* Symbol, variable and name lookup.
2    Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 
4    This file is part of libctf.
5 
6    libctf is free software; you can redistribute it and/or modify it under
7    the terms of the GNU General Public License as published by the Free
8    Software Foundation; either version 3, or (at your option) any later
9    version.
10 
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14    See the GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; see the file COPYING.  If not see
18    <http://www.gnu.org/licenses/>.  */
19 
20 #include <ctf-impl.h>
21 #include <elf.h>
22 #include <string.h>
23 #include <assert.h>
24 
25 /* Grow the pptrtab so that it is at least NEW_LEN long.  */
26 static int
27 grow_pptrtab (ctf_dict_t *fp, size_t new_len)
28 {
29   uint32_t *new_pptrtab;
30 
31   if ((new_pptrtab = realloc (fp->ctf_pptrtab, sizeof (uint32_t)
32 			      * new_len)) == NULL)
33     return (ctf_set_errno (fp, ENOMEM));
34 
35   fp->ctf_pptrtab = new_pptrtab;
36 
37   memset (fp->ctf_pptrtab + fp->ctf_pptrtab_len, 0,
38 	  sizeof (uint32_t) * (new_len - fp->ctf_pptrtab_len));
39 
40   fp->ctf_pptrtab_len = new_len;
41   return 0;
42 }
43 
44 /* Update entries in the pptrtab that relate to types newly added in the
45    child.  */
46 static int
47 refresh_pptrtab (ctf_dict_t *fp, ctf_dict_t *pfp)
48 {
49   uint32_t i;
50   for (i = fp->ctf_pptrtab_typemax; i <= fp->ctf_typemax; i++)
51     {
52       ctf_id_t type = LCTF_INDEX_TO_TYPE (fp, i, 1);
53       ctf_id_t reffed_type;
54 
55       if (ctf_type_kind (fp, type) != CTF_K_POINTER)
56 	continue;
57 
58       reffed_type = ctf_type_reference (fp, type);
59 
60       if (LCTF_TYPE_ISPARENT (fp, reffed_type))
61 	{
62 	  uint32_t idx = LCTF_TYPE_TO_INDEX (fp, reffed_type);
63 
64 	  /* Guard against references to invalid types.  No need to consider
65 	     the CTF dict corrupt in this case: this pointer just can't be a
66 	     pointer to any type we know about.  */
67 	  if (idx <= pfp->ctf_typemax)
68 	    {
69 	      if (idx >= fp->ctf_pptrtab_len
70 		  && grow_pptrtab (fp, pfp->ctf_ptrtab_len) < 0)
71 		return -1;			/* errno is set for us.  */
72 
73 	      fp->ctf_pptrtab[idx] = i;
74 	    }
75 	}
76     }
77 
78   fp->ctf_pptrtab_typemax = fp->ctf_typemax;
79 
80   return 0;
81 }
82 
83 /* Compare the given input string and length against a table of known C storage
84    qualifier keywords.  We just ignore these in ctf_lookup_by_name, below.  To
85    do this quickly, we use a pre-computed Perfect Hash Function similar to the
86    technique originally described in the classic paper:
87 
88    R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple",
89    Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19.
90 
91    For an input string S of length N, we use hash H = S[N - 1] + N - 105, which
92    for the current set of qualifiers yields a unique H in the range [0 .. 20].
93    The hash can be modified when the keyword set changes as necessary.  We also
94    store the length of each keyword and check it prior to the final strcmp().
95 
96    TODO: just use gperf.  */
97 
98 static int
99 isqualifier (const char *s, size_t len)
100 {
101   static const struct qual
102   {
103     const char *q_name;
104     size_t q_len;
105   } qhash[] = {
106     {"static", 6}, {"", 0}, {"", 0}, {"", 0},
107     {"volatile", 8}, {"", 0}, {"", 0}, {"", 0}, {"", 0},
108     {"", 0}, {"auto", 4}, {"extern", 6}, {"", 0}, {"", 0},
109     {"", 0}, {"", 0}, {"const", 5}, {"register", 8},
110     {"", 0}, {"restrict", 8}, {"_Restrict", 9}
111   };
112 
113   int h = s[len - 1] + (int) len - 105;
114   const struct qual *qp;
115 
116   if (h < 0 || (size_t) h >= sizeof (qhash) / sizeof (qhash[0]))
117     return 0;
118 
119   qp = &qhash[h];
120 
121   return ((size_t) len == qp->q_len &&
122 	  strncmp (qp->q_name, s, qp->q_len) == 0);
123 }
124 
125 /* Attempt to convert the given C type name into the corresponding CTF type ID.
126    It is not possible to do complete and proper conversion of type names
127    without implementing a more full-fledged parser, which is necessary to
128    handle things like types that are function pointers to functions that
129    have arguments that are function pointers, and fun stuff like that.
130    Instead, this function implements a very simple conversion algorithm that
131    finds the things that we actually care about: structs, unions, enums,
132    integers, floats, typedefs, and pointers to any of these named types.  */
133 
134 static ctf_id_t
135 ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child,
136 			     const char *name)
137 {
138   static const char delimiters[] = " \t\n\r\v\f*";
139 
140   const ctf_lookup_t *lp;
141   const char *p, *q, *end;
142   ctf_id_t type = 0;
143   ctf_id_t ntype, ptype;
144 
145   if (name == NULL)
146     return (ctf_set_typed_errno (fp, EINVAL));
147 
148   for (p = name, end = name + strlen (name); *p != '\0'; p = q)
149     {
150       while (isspace ((int) *p))
151 	p++;			/* Skip leading whitespace.  */
152 
153       if (p == end)
154 	break;
155 
156       if ((q = strpbrk (p + 1, delimiters)) == NULL)
157 	q = end;		/* Compare until end.  */
158 
159       if (*p == '*')
160 	{
161 	  /* Find a pointer to type by looking in child->ctf_pptrtab (if child
162 	     is set) and fp->ctf_ptrtab.  If we can't find a pointer to the
163 	     given type, see if we can compute a pointer to the type resulting
164 	     from resolving the type down to its base type and use that instead.
165 	     This helps with cases where the CTF data includes "struct foo *"
166 	     but not "foo_t *" and the user tries to access "foo_t *" in the
167 	     debugger.
168 
169 	     There is extra complexity here because uninitialized elements in
170 	     the pptrtab and ptrtab are set to zero, but zero (as the type ID
171 	     meaning the unimplemented type) is a valid return type from
172 	     ctf_lookup_by_name.  (Pointers to types are never of type 0, so
173 	     this is unambiguous, just fiddly to deal with.)  */
174 
175 	  uint32_t idx = LCTF_TYPE_TO_INDEX (fp, type);
176 	  int in_child = 0;
177 
178 	  ntype = CTF_ERR;
179 	  if (child && idx < child->ctf_pptrtab_len)
180 	    {
181 	      ntype = child->ctf_pptrtab[idx];
182 	      if (ntype)
183 		in_child = 1;
184 	      else
185 		ntype = CTF_ERR;
186 	    }
187 
188 	  if (ntype == CTF_ERR)
189 	    {
190 	      ntype = fp->ctf_ptrtab[idx];
191 	      if (ntype == 0)
192 		ntype = CTF_ERR;
193 	    }
194 
195 	  /* Try resolving to its base type and check again.  */
196 	  if (ntype == CTF_ERR)
197 	    {
198 	      if (child)
199 		ntype = ctf_type_resolve_unsliced (child, type);
200 	      else
201 		ntype = ctf_type_resolve_unsliced (fp, type);
202 
203 	      if (ntype == CTF_ERR)
204 		goto notype;
205 
206 	      idx = LCTF_TYPE_TO_INDEX (fp, ntype);
207 
208 	      ntype = CTF_ERR;
209 	      if (child && idx < child->ctf_pptrtab_len)
210 		{
211 		  ntype = child->ctf_pptrtab[idx];
212 		  if (ntype)
213 		    in_child = 1;
214 		  else
215 		    ntype = CTF_ERR;
216 		}
217 
218 	      if (ntype == CTF_ERR)
219 		{
220 		  ntype = fp->ctf_ptrtab[idx];
221 		  if (ntype == 0)
222 		    ntype = CTF_ERR;
223 		}
224 	      if (ntype == CTF_ERR)
225 		goto notype;
226 	    }
227 
228 	  type = LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)
229 				     || in_child);
230 
231 	  /* We are looking up a type in the parent, but the pointed-to type is
232 	     in the child.  Switch to looking in the child: if we need to go
233 	     back into the parent, we can recurse again.  */
234 	  if (in_child)
235 	    {
236 	      fp = child;
237 	      child = NULL;
238 	    }
239 
240 	  q = p + 1;
241 	  continue;
242 	}
243 
244       if (isqualifier (p, (size_t) (q - p)))
245 	continue;		/* Skip qualifier keyword.  */
246 
247       for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++)
248 	{
249 	  /* TODO: This is not MT-safe.  */
250 	  if ((lp->ctl_prefix[0] == '\0' ||
251 	       strncmp (p, lp->ctl_prefix, (size_t) (q - p)) == 0) &&
252 	      (size_t) (q - p) >= lp->ctl_len)
253 	    {
254 	      for (p += lp->ctl_len; isspace ((int) *p); p++)
255 		continue;	/* Skip prefix and next whitespace.  */
256 
257 	      if ((q = strchr (p, '*')) == NULL)
258 		q = end;	/* Compare until end.  */
259 
260 	      while (isspace ((int) q[-1]))
261 		q--;		/* Exclude trailing whitespace.  */
262 
263 	      /* Expand and/or allocate storage for a slice of the name, then
264 		 copy it in.  */
265 
266 	      if (fp->ctf_tmp_typeslicelen >= (size_t) (q - p) + 1)
267 		{
268 		  memcpy (fp->ctf_tmp_typeslice, p, (size_t) (q - p));
269 		  fp->ctf_tmp_typeslice[(size_t) (q - p)] = '\0';
270 		}
271 	      else
272 		{
273 		  free (fp->ctf_tmp_typeslice);
274 		  fp->ctf_tmp_typeslice = xstrndup (p, (size_t) (q - p));
275 		  if (fp->ctf_tmp_typeslice == NULL)
276 		    return ctf_set_typed_errno (fp, ENOMEM);
277 		}
278 
279 	      if ((type = (ctf_id_t) (uintptr_t)
280 		   ctf_dynhash_lookup (lp->ctl_hash,
281 				       fp->ctf_tmp_typeslice)) == 0)
282 		goto notype;
283 
284 	      break;
285 	    }
286 	}
287 
288       if (lp->ctl_prefix == NULL)
289 	goto notype;
290     }
291 
292   if (*p != '\0' || type == 0)
293     return (ctf_set_typed_errno (fp, ECTF_SYNTAX));
294 
295   return type;
296 
297  notype:
298   ctf_set_errno (fp, ECTF_NOTYPE);
299   if (fp->ctf_parent != NULL)
300     {
301       /* Need to look up in the parent, from the child's perspective.
302 	 Make sure the pptrtab is up to date.  */
303 
304       if (fp->ctf_pptrtab_typemax < fp->ctf_typemax)
305 	{
306 	  if (refresh_pptrtab (fp, fp->ctf_parent) < 0)
307 	    return CTF_ERR;			/* errno is set for us.  */
308 	}
309 
310       if ((ptype = ctf_lookup_by_name_internal (fp->ctf_parent, fp,
311 						name)) != CTF_ERR)
312 	return ptype;
313       return (ctf_set_typed_errno (fp, ctf_errno (fp->ctf_parent)));
314     }
315 
316   return CTF_ERR;
317 }
318 
319 ctf_id_t
320 ctf_lookup_by_name (ctf_dict_t *fp, const char *name)
321 {
322   return ctf_lookup_by_name_internal (fp, NULL, name);
323 }
324 
325 /* Return the pointer to the internal CTF type data corresponding to the
326    given type ID.  If the ID is invalid, the function returns NULL.
327    This function is not exported outside of the library.  */
328 
329 const ctf_type_t *
330 ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type)
331 {
332   ctf_dict_t *fp = *fpp;
333   ctf_id_t idx;
334 
335   if ((fp = ctf_get_dict (fp, type)) == NULL)
336     {
337       (void) ctf_set_errno (*fpp, ECTF_NOPARENT);
338       return NULL;
339     }
340 
341   idx = LCTF_TYPE_TO_INDEX (fp, type);
342   if (idx > 0 && (unsigned long) idx <= fp->ctf_typemax)
343     {
344       *fpp = fp;		/* Possibly the parent CTF dict.  */
345       return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
346     }
347 
348   (void) ctf_set_errno (*fpp, ECTF_BADID);
349   return NULL;
350 }
351 
352 typedef struct ctf_lookup_idx_key
353 {
354   ctf_dict_t *clik_fp;
355   const char *clik_name;
356   uint32_t *clik_names;
357 } ctf_lookup_idx_key_t;
358 
359 /* A bsearch function for variable names.  */
360 
361 static int
362 ctf_lookup_var (const void *key_, const void *lookup_)
363 {
364   const ctf_lookup_idx_key_t *key = key_;
365   const ctf_varent_t *lookup = lookup_;
366 
367   return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, lookup->ctv_name)));
368 }
369 
370 /* Given a variable name, return the type of the variable with that name.
371    Look only in this dict, not in the parent. */
372 
373 ctf_id_t
374 ctf_lookup_variable_here (ctf_dict_t *fp, const char *name)
375 {
376   ctf_dvdef_t *dvd = ctf_dvd_lookup (fp, name);
377   ctf_varent_t *ent;
378   ctf_lookup_idx_key_t key = { fp, name, NULL };
379 
380   if (dvd != NULL)
381     return dvd->dvd_type;
382 
383   /* This array is sorted, so we can bsearch for it.  */
384 
385   ent = bsearch (&key, fp->ctf_vars, fp->ctf_nvars, sizeof (ctf_varent_t),
386 		 ctf_lookup_var);
387 
388   if (ent == NULL)
389       return (ctf_set_typed_errno (fp, ECTF_NOTYPEDAT));
390 
391   return ent->ctv_type;
392 }
393 
394 /* As above, but look in the parent too.  */
395 
396 ctf_id_t
397 ctf_lookup_variable (ctf_dict_t *fp, const char *name)
398 {
399   ctf_id_t type;
400 
401   if ((type = ctf_lookup_variable_here (fp, name)) == CTF_ERR)
402     {
403       if (ctf_errno (fp) == ECTF_NOTYPEDAT && fp->ctf_parent != NULL)
404 	{
405 	  if ((type = ctf_lookup_variable_here (fp->ctf_parent, name)) != CTF_ERR)
406 	    return type;
407 	  return (ctf_set_typed_errno (fp, ctf_errno (fp->ctf_parent)));
408 	}
409 
410       return -1;				/* errno is set for us.  */
411     }
412 
413   return type;
414 }
415 
416 typedef struct ctf_symidx_sort_arg_cb
417 {
418   ctf_dict_t *fp;
419   uint32_t *names;
420 } ctf_symidx_sort_arg_cb_t;
421 
422 static int
423 sort_symidx_by_name (const void *one_, const void *two_, void *arg_)
424 {
425   const uint32_t *one = one_;
426   const uint32_t *two = two_;
427   ctf_symidx_sort_arg_cb_t *arg = arg_;
428 
429   return (strcmp (ctf_strptr (arg->fp, arg->names[*one]),
430 		  ctf_strptr (arg->fp, arg->names[*two])));
431 }
432 
433 /* Sort a symbol index section by name.  Takes a 1:1 mapping of names to the
434    corresponding symbol table.  Returns a lexicographically sorted array of idx
435    indexes (and thus, of indexes into the corresponding func info / data object
436    section).  */
437 
438 static uint32_t *
439 ctf_symidx_sort (ctf_dict_t *fp, uint32_t *idx, size_t *nidx,
440 			 size_t len)
441 {
442   uint32_t *sorted;
443   size_t i;
444 
445   if ((sorted = malloc (len)) == NULL)
446     {
447       ctf_set_errno (fp, ENOMEM);
448       return NULL;
449     }
450 
451   *nidx = len / sizeof (uint32_t);
452   for (i = 0; i < *nidx; i++)
453     sorted[i] = i;
454 
455   if (!(fp->ctf_header->cth_flags & CTF_F_IDXSORTED))
456     {
457       ctf_symidx_sort_arg_cb_t arg = { fp, idx };
458       ctf_dprintf ("Index section unsorted: sorting.\n");
459       ctf_qsort_r (sorted, *nidx, sizeof (uint32_t), sort_symidx_by_name, &arg);
460       fp->ctf_header->cth_flags |= CTF_F_IDXSORTED;
461     }
462 
463   return sorted;
464 }
465 
466 /* Given a symbol index, return the name of that symbol from the table provided
467    by ctf_link_shuffle_syms, or failing that from the secondary string table, or
468    the null string.  */
469 static const char *
470 ctf_lookup_symbol_name (ctf_dict_t *fp, unsigned long symidx)
471 {
472   const ctf_sect_t *sp = &fp->ctf_ext_symtab;
473   ctf_link_sym_t sym;
474   int err;
475 
476   if (fp->ctf_dynsymidx)
477     {
478       err = EINVAL;
479       if (symidx > fp->ctf_dynsymmax)
480 	goto try_parent;
481 
482       ctf_link_sym_t *symp = fp->ctf_dynsymidx[symidx];
483 
484       if (!symp)
485 	goto try_parent;
486 
487       return symp->st_name;
488     }
489 
490   err = ECTF_NOSYMTAB;
491   if (sp->cts_data == NULL)
492     goto try_parent;
493 
494   if (symidx >= fp->ctf_nsyms)
495     goto try_parent;
496 
497   switch (sp->cts_entsize)
498     {
499     case sizeof (Elf64_Sym):
500       {
501 	const Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data + symidx;
502 	ctf_elf64_to_link_sym (fp, &sym, symp, symidx);
503       }
504       break;
505     case sizeof (Elf32_Sym):
506       {
507 	const Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data + symidx;
508 	ctf_elf32_to_link_sym (fp, &sym, symp, symidx);
509       }
510       break;
511     default:
512       ctf_set_errno (fp, ECTF_SYMTAB);
513       return _CTF_NULLSTR;
514     }
515 
516   assert (!sym.st_nameidx_set);
517 
518   return sym.st_name;
519 
520  try_parent:
521   if (fp->ctf_parent)
522     {
523       const char *ret;
524       ret = ctf_lookup_symbol_name (fp->ctf_parent, symidx);
525       if (ret == NULL)
526 	ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
527       return ret;
528     }
529   else
530     {
531       ctf_set_errno (fp, err);
532       return _CTF_NULLSTR;
533     }
534 }
535 
536 /* Given a symbol name, return the index of that symbol, or -1 on error or if
537    not found.  If is_function is >= 0, return only function or data object
538    symbols, respectively.  */
539 static unsigned long
540 ctf_lookup_symbol_idx (ctf_dict_t *fp, const char *symname, int try_parent,
541 		       int is_function)
542 {
543   const ctf_sect_t *sp = &fp->ctf_ext_symtab;
544   ctf_link_sym_t sym;
545   void *known_idx;
546   int err;
547   ctf_dict_t *cache = fp;
548 
549   if (fp->ctf_dynsyms)
550     {
551       err = EINVAL;
552 
553       ctf_link_sym_t *symp;
554 
555       if (((symp = ctf_dynhash_lookup (fp->ctf_dynsyms, symname)) == NULL)
556 	  || (symp->st_type != STT_OBJECT && is_function == 0)
557 	  || (symp->st_type != STT_FUNC && is_function == 1))
558 	goto try_parent;
559 
560       return symp->st_symidx;
561     }
562 
563   err = ECTF_NOSYMTAB;
564   if (sp->cts_data == NULL)
565     goto try_parent;
566 
567   /* First, try a hash lookup to see if we have already spotted this symbol
568      during a past iteration: create the hash first if need be.  The
569      lifespan of the strings is equal to the lifespan of the cts_data, so we
570      don't need to strdup them.  If this dict was opened as part of an
571      archive, and this archive has a crossdict_cache to cache results that
572      are the same across all dicts in an archive, use it.  */
573 
574   if (fp->ctf_archive && fp->ctf_archive->ctfi_crossdict_cache)
575     cache = fp->ctf_archive->ctfi_crossdict_cache;
576 
577   if (!cache->ctf_symhash_func)
578     if ((cache->ctf_symhash_func = ctf_dynhash_create (ctf_hash_string,
579 						       ctf_hash_eq_string,
580 						       NULL, NULL)) == NULL)
581       goto oom;
582 
583   if (!cache->ctf_symhash_objt)
584     if ((cache->ctf_symhash_objt = ctf_dynhash_create (ctf_hash_string,
585 						       ctf_hash_eq_string,
586 						       NULL, NULL)) == NULL)
587       goto oom;
588 
589   if (is_function != 0 &&
590       ctf_dynhash_lookup_kv (cache->ctf_symhash_func, symname, NULL, &known_idx))
591     return (unsigned long) (uintptr_t) known_idx;
592 
593   if (is_function != 1 &&
594       ctf_dynhash_lookup_kv (cache->ctf_symhash_objt, symname, NULL, &known_idx))
595     return (unsigned long) (uintptr_t) known_idx;
596 
597   /* Hash lookup unsuccessful: linear search, populating the hashtab for later
598      lookups as we go.  */
599 
600   for (; cache->ctf_symhash_latest < sp->cts_size / sp->cts_entsize;
601        cache->ctf_symhash_latest++)
602     {
603       ctf_dynhash_t *h;
604 
605       switch (sp->cts_entsize)
606 	{
607 	case sizeof (Elf64_Sym):
608 	  {
609 	    Elf64_Sym *symp = (Elf64_Sym *) sp->cts_data;
610 
611 	    ctf_elf64_to_link_sym (fp, &sym, &symp[cache->ctf_symhash_latest],
612 				   cache->ctf_symhash_latest);
613 	  }
614 	  break;
615 	case sizeof (Elf32_Sym):
616 	  {
617 	    Elf32_Sym *symp = (Elf32_Sym *) sp->cts_data;
618 	    ctf_elf32_to_link_sym (fp, &sym, &symp[cache->ctf_symhash_latest],
619 				   cache->ctf_symhash_latest);
620 	    break;
621 	  }
622 	default:
623 	  ctf_set_errno (fp, ECTF_SYMTAB);
624 	  return (unsigned long) -1;
625 	}
626 
627       if (sym.st_type == STT_FUNC)
628 	h = cache->ctf_symhash_func;
629       else if (sym.st_type == STT_OBJECT)
630 	h = cache->ctf_symhash_objt;
631       else
632 	continue;					/* Not of interest.  */
633 
634       if (!ctf_dynhash_lookup_kv (h, sym.st_name,
635 				  NULL, NULL))
636 	if (ctf_dynhash_cinsert (h, sym.st_name,
637 				 (const void *) (uintptr_t)
638 				 cache->ctf_symhash_latest) < 0)
639 	  goto oom;
640       if (strcmp (sym.st_name, symname) == 0)
641 	return cache->ctf_symhash_latest++;
642     }
643 
644   /* Searched everything, still not found.  */
645 
646   return (unsigned long) -1;
647 
648  try_parent:
649   if (fp->ctf_parent && try_parent)
650     {
651       unsigned long psym;
652 
653       if ((psym = ctf_lookup_symbol_idx (fp->ctf_parent, symname, try_parent,
654 					 is_function))
655           != (unsigned long) -1)
656         return psym;
657 
658       ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
659       return (unsigned long) -1;
660     }
661   else
662     {
663       ctf_set_errno (fp, err);
664       return (unsigned long) -1;
665     }
666 oom:
667   ctf_set_errno (fp, ENOMEM);
668   ctf_err_warn (fp, 0, 0, _("cannot allocate memory for symbol "
669 			    "lookup hashtab"));
670   return (unsigned long) -1;
671 
672 }
673 
674 ctf_id_t
675 ctf_symbol_next_static (ctf_dict_t *fp, ctf_next_t **it, const char **name,
676 			int functions);
677 
678 /* Iterate over all symbols with types: if FUNC, function symbols,
679    otherwise, data symbols.  The name argument is not optional.  The return
680    order is arbitrary, though is likely to be in symbol index or name order.
681    Changing the value of 'functions' in the middle of iteration has
682    unpredictable effects (probably skipping symbols, etc) and is not
683    recommended.  Adding symbols while iteration is underway may also lead
684    to other symbols being skipped.  */
685 
686 ctf_id_t
687 ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
688 		 int functions)
689 {
690   ctf_id_t sym = CTF_ERR;
691   ctf_next_t *i = *it;
692   int err;
693 
694   if (!i)
695     {
696       if ((i = ctf_next_create ()) == NULL)
697 	return ctf_set_typed_errno (fp, ENOMEM);
698 
699       i->cu.ctn_fp = fp;
700       i->ctn_iter_fun = (void (*) (void)) ctf_symbol_next;
701       i->ctn_n = 0;
702       *it = i;
703     }
704 
705   if ((void (*) (void)) ctf_symbol_next != i->ctn_iter_fun)
706     return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFUN));
707 
708   if (fp != i->cu.ctn_fp)
709     return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFP));
710 
711   /* Check the dynamic set of names first, to allow previously-written names
712      to be replaced with dynamic ones (there is still no way to remove them,
713      though).
714 
715      We intentionally use raw access, not ctf_lookup_by_symbol, to avoid
716      incurring additional sorting cost for unsorted symtypetabs coming from the
717      compiler, to allow ctf_symbol_next to work in the absence of a symtab, and
718      finally because it's easier to work out what the name of each symbol is if
719      we do that.  */
720 
721   ctf_dynhash_t *dynh = functions ? fp->ctf_funchash : fp->ctf_objthash;
722   void *dyn_name = NULL, *dyn_value = NULL;
723   size_t dyn_els = dynh ? ctf_dynhash_elements (dynh) : 0;
724 
725   if (i->ctn_n < dyn_els)
726     {
727       err = ctf_dynhash_next (dynh, &i->ctn_next, &dyn_name, &dyn_value);
728 
729       /* This covers errors and also end-of-iteration.  */
730       if (err != 0)
731 	{
732 	  ctf_next_destroy (i);
733 	  *it = NULL;
734 	  return ctf_set_typed_errno (fp, err);
735 	}
736 
737       *name = dyn_name;
738       sym = (ctf_id_t) (uintptr_t) dyn_value;
739       i->ctn_n++;
740 
741       return sym;
742     }
743 
744   return ctf_symbol_next_static (fp, it, name, functions);
745 }
746 
747 /* ctf_symbol_next, but only for static symbols.  Mostly an internal
748    implementation detail of ctf_symbol_next, but also used to simplify
749    serialization.  */
750 ctf_id_t
751 ctf_symbol_next_static (ctf_dict_t *fp, ctf_next_t **it, const char **name,
752 			int functions)
753 {
754   ctf_id_t sym = CTF_ERR;
755   ctf_next_t *i = *it;
756   ctf_dynhash_t *dynh = functions ? fp->ctf_funchash : fp->ctf_objthash;
757   size_t dyn_els = dynh ? ctf_dynhash_elements (dynh) : 0;
758 
759   /* Only relevant for direct internal-to-library calls, not via
760      ctf_symbol_next (but important then).  */
761 
762   if (!i)
763     {
764       if ((i = ctf_next_create ()) == NULL)
765 	return ctf_set_typed_errno (fp, ENOMEM);
766 
767       i->cu.ctn_fp = fp;
768       i->ctn_iter_fun = (void (*) (void)) ctf_symbol_next;
769       i->ctn_n = dyn_els;
770       *it = i;
771     }
772 
773   if ((void (*) (void)) ctf_symbol_next != i->ctn_iter_fun)
774     return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFUN));
775 
776   if (fp != i->cu.ctn_fp)
777     return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFP));
778 
779   /* TODO-v4: Indexed after non-indexed portions?  */
780 
781   if ((!functions && fp->ctf_objtidx_names) ||
782       (functions && fp->ctf_funcidx_names))
783     {
784       ctf_header_t *hp = fp->ctf_header;
785       uint32_t *idx = functions ? fp->ctf_funcidx_names : fp->ctf_objtidx_names;
786       uint32_t *tab;
787       size_t len;
788 
789       if (functions)
790 	{
791 	  len = (hp->cth_varoff - hp->cth_funcidxoff) / sizeof (uint32_t);
792 	  tab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
793 	}
794       else
795 	{
796 	  len = (hp->cth_funcidxoff - hp->cth_objtidxoff) / sizeof (uint32_t);
797 	  tab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff);
798 	}
799 
800       do
801 	{
802 	  if (i->ctn_n - dyn_els >= len)
803 	    goto end;
804 
805 	  *name = ctf_strptr (fp, idx[i->ctn_n - dyn_els]);
806 	  sym = tab[i->ctn_n - dyn_els];
807 	  i->ctn_n++;
808 	}
809       while (sym == -1u || sym == 0);
810     }
811   else
812     {
813       /* Skip over pads in ctf_sxlate, padding for typeless symbols in the
814 	 symtypetab itself, and symbols in the wrong table.  */
815       for (; i->ctn_n - dyn_els < fp->ctf_nsyms; i->ctn_n++)
816 	{
817 	  ctf_header_t *hp = fp->ctf_header;
818 	  size_t n = i->ctn_n - dyn_els;
819 
820 	  if (fp->ctf_sxlate[n] == -1u)
821 	    continue;
822 
823 	  sym = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[n]);
824 
825 	  if (sym == 0)
826 	    continue;
827 
828 	  if (functions)
829 	    {
830 	      if (fp->ctf_sxlate[n] >= hp->cth_funcoff
831 		  && fp->ctf_sxlate[n] < hp->cth_objtidxoff)
832 		break;
833 	    }
834 	  else
835 	    {
836 	      if (fp->ctf_sxlate[n] >= hp->cth_objtoff
837 		  && fp->ctf_sxlate[n] < hp->cth_funcoff)
838 		break;
839 	    }
840 	}
841 
842       if (i->ctn_n - dyn_els >= fp->ctf_nsyms)
843 	goto end;
844 
845       *name = ctf_lookup_symbol_name (fp, i->ctn_n - dyn_els);
846       i->ctn_n++;
847     }
848 
849   return sym;
850 
851  end:
852   ctf_next_destroy (i);
853   *it = NULL;
854   return (ctf_set_typed_errno (fp, ECTF_NEXT_END));
855 }
856 
857 /* A bsearch function for function and object index names.  */
858 
859 static int
860 ctf_lookup_idx_name (const void *key_, const void *idx_)
861 {
862   const ctf_lookup_idx_key_t *key = key_;
863   const uint32_t *idx = idx_;
864 
865   return (strcmp (key->clik_name, ctf_strptr (key->clik_fp, key->clik_names[*idx])));
866 }
867 
868 /* Given a symbol name or (failing that) number, look up that symbol in the
869    function or object index table (which must exist).  Return 0 if not found
870    there (or pad).  */
871 
872 static ctf_id_t
873 ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
874 			const char *symname, int is_function)
875 {
876   struct ctf_header *hp = fp->ctf_header;
877   uint32_t *symtypetab;
878   uint32_t *names;
879   uint32_t *sxlate;
880   size_t nidx;
881 
882   if (symname == NULL)
883     symname = ctf_lookup_symbol_name (fp, symidx);
884 
885   /* Dynamic dict with no static portion: just return.  */
886   if (!hp)
887     {
888       ctf_dprintf ("%s not found in idx: dict is dynamic\n", symname);
889       return 0;
890     }
891 
892   ctf_dprintf ("Looking up type of object with symtab idx %lx or name %s in "
893 	       "indexed symtypetab\n", symidx, symname);
894 
895   if (symname[0] == '\0')
896     return CTF_ERR;					/* errno is set for us.  */
897 
898   if (is_function)
899     {
900       if (!fp->ctf_funcidx_sxlate)
901 	{
902 	  if ((fp->ctf_funcidx_sxlate
903 	       = ctf_symidx_sort (fp, (uint32_t *)
904 				  (fp->ctf_buf + hp->cth_funcidxoff),
905 				  &fp->ctf_nfuncidx,
906 				  hp->cth_varoff - hp->cth_funcidxoff))
907 	      == NULL)
908 	    {
909 	      ctf_err_warn (fp, 0, 0, _("cannot sort function symidx"));
910 	      return CTF_ERR;				/* errno is set for us.  */
911 	    }
912 	}
913       symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
914       sxlate = fp->ctf_funcidx_sxlate;
915       names = fp->ctf_funcidx_names;
916       nidx = fp->ctf_nfuncidx;
917     }
918   else
919     {
920       if (!fp->ctf_objtidx_sxlate)
921 	{
922 	  if ((fp->ctf_objtidx_sxlate
923 	       = ctf_symidx_sort (fp, (uint32_t *)
924 				  (fp->ctf_buf + hp->cth_objtidxoff),
925 				  &fp->ctf_nobjtidx,
926 				  hp->cth_funcidxoff - hp->cth_objtidxoff))
927 	      == NULL)
928 	    {
929 	      ctf_err_warn (fp, 0, 0, _("cannot sort object symidx"));
930 	      return CTF_ERR;				/* errno is set for us. */
931 	    }
932 	}
933 
934       symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_objtoff);
935       sxlate = fp->ctf_objtidx_sxlate;
936       names = fp->ctf_objtidx_names;
937       nidx = fp->ctf_nobjtidx;
938     }
939 
940   ctf_lookup_idx_key_t key = { fp, symname, names };
941   uint32_t *idx;
942 
943   idx = bsearch (&key, sxlate, nidx, sizeof (uint32_t), ctf_lookup_idx_name);
944 
945   if (!idx)
946     {
947       ctf_dprintf ("%s not found in idx\n", symname);
948       return 0;
949     }
950 
951   /* Should be impossible, but be paranoid.  */
952   if ((idx - sxlate) > (ptrdiff_t) nidx)
953     return (ctf_set_typed_errno (fp, ECTF_CORRUPT));
954 
955   ctf_dprintf ("Symbol %lx (%s) is of type %x\n", symidx, symname,
956 	       symtypetab[*idx]);
957   return symtypetab[*idx];
958 }
959 
960 /* Given a symbol name or (if NULL) symbol index, return the type of the
961    function or data object described by the corresponding entry in the symbol
962    table.  We can only return symbols in read-only dicts and in dicts for which
963    ctf_link_shuffle_syms has been called to assign symbol indexes to symbol
964    names.
965 
966    If try_parent is false, do not check the parent dict too.
967 
968    If is_function is > -1, only look for data objects or functions in
969    particular.  */
970 
971 ctf_id_t
972 ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
973 			   const char *symname, int try_parent,
974 			   int is_function)
975 {
976   const ctf_sect_t *sp = &fp->ctf_ext_symtab;
977   ctf_id_t type = 0;
978   int err = 0;
979 
980   /* Shuffled dynsymidx present?  Use that.  For now, the dynsymidx and
981      shuffled-symbol lookup only support dynamically-added symbols, because
982      this interface is meant for use by linkers, and linkers are only going
983      to report symbols against newly-created, freshly-ctf_link'ed dicts: so
984      there will be no static component in any case.  */
985   if (fp->ctf_dynsymidx)
986     {
987       const ctf_link_sym_t *sym;
988 
989       if (symname)
990 	ctf_dprintf ("Looking up type of object with symname %s in "
991 		     "writable dict symtypetab\n", symname);
992       else
993 	ctf_dprintf ("Looking up type of object with symtab idx %lx in "
994 		     "writable dict symtypetab\n", symidx);
995 
996       /* No name? Need to look it up.  */
997       if (!symname)
998 	{
999 	  err = EINVAL;
1000 	  if (symidx > fp->ctf_dynsymmax)
1001 	    goto try_parent;
1002 
1003 	  sym = fp->ctf_dynsymidx[symidx];
1004 	  err = ECTF_NOTYPEDAT;
1005 	  if (!sym || (sym->st_type != STT_OBJECT && sym->st_type != STT_FUNC)
1006 	      || (sym->st_type != STT_OBJECT && is_function == 0)
1007 	      || (sym->st_type != STT_FUNC && is_function == 1))
1008 	    goto try_parent;
1009 
1010 	  if (!ctf_assert (fp, !sym->st_nameidx_set))
1011 	    return CTF_ERR;
1012 	  symname = sym->st_name;
1013      }
1014 
1015       if (fp->ctf_objthash == NULL
1016 	  || is_function == 1
1017 	  || (type = (ctf_id_t) (uintptr_t)
1018 	      ctf_dynhash_lookup (fp->ctf_objthash, symname)) == 0)
1019 	{
1020 	  if (fp->ctf_funchash == NULL
1021 	      || is_function == 0
1022 	      || (type = (ctf_id_t) (uintptr_t)
1023 		  ctf_dynhash_lookup (fp->ctf_funchash, symname)) == 0)
1024 	    goto try_parent;
1025 	}
1026 
1027       return type;
1028     }
1029 
1030   /* Dict not shuffled: look for a dynamic sym first, and look it up
1031      directly.  */
1032   if (symname)
1033     {
1034       if (fp->ctf_objthash != NULL
1035 	  && is_function != 1
1036 	  && ((type = (ctf_id_t) (uintptr_t)
1037 	       ctf_dynhash_lookup (fp->ctf_objthash, symname)) != 0))
1038 	return type;
1039 
1040       if (fp->ctf_funchash != NULL
1041 	  && is_function != 0
1042 	  && ((type = (ctf_id_t) (uintptr_t)
1043 	       ctf_dynhash_lookup (fp->ctf_funchash, symname)) != 0))
1044 	return type;
1045     }
1046 
1047   err = ECTF_NOSYMTAB;
1048   if (sp->cts_data == NULL && symname == NULL &&
1049       ((is_function && !fp->ctf_funcidx_names) ||
1050        (!is_function && !fp->ctf_objtidx_names)))
1051     goto try_parent;
1052 
1053   /* This covers both out-of-range lookups by index and a dynamic dict which
1054      hasn't been shuffled yet.  */
1055   err = EINVAL;
1056   if (symname == NULL && symidx >= fp->ctf_nsyms)
1057     goto try_parent;
1058 
1059   /* Try an indexed lookup.  */
1060 
1061   if (fp->ctf_objtidx_names && is_function != 1)
1062     {
1063       if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 0)) == CTF_ERR)
1064 	return CTF_ERR;				/* errno is set for us.  */
1065     }
1066   if (type == 0 && fp->ctf_funcidx_names && is_function != 0)
1067     {
1068       if ((type = ctf_try_lookup_indexed (fp, symidx, symname, 1)) == CTF_ERR)
1069 	return CTF_ERR;				/* errno is set for us.  */
1070     }
1071   if (type != 0)
1072     return type;
1073 
1074   /* Indexed but no symbol found -> not present, try the parent.  */
1075   err = ECTF_NOTYPEDAT;
1076   if (fp->ctf_objtidx_names && fp->ctf_funcidx_names)
1077     goto try_parent;
1078 
1079   /* Table must be nonindexed.  */
1080 
1081   ctf_dprintf ("Looking up object type %lx in 1:1 dict symtypetab\n", symidx);
1082 
1083   if (symname != NULL)
1084     if ((symidx = ctf_lookup_symbol_idx (fp, symname, try_parent, is_function))
1085 	== (unsigned long) -1)
1086       goto try_parent;
1087 
1088   if (fp->ctf_sxlate[symidx] == -1u)
1089     goto try_parent;
1090 
1091   type = *(uint32_t *) ((uintptr_t) fp->ctf_buf + fp->ctf_sxlate[symidx]);
1092 
1093   if (type == 0)
1094     goto try_parent;
1095 
1096   return type;
1097 
1098  try_parent:
1099   if (!try_parent)
1100     return ctf_set_errno (fp, err);
1101 
1102   if (fp->ctf_parent)
1103     {
1104       ctf_id_t ret = ctf_lookup_by_sym_or_name (fp->ctf_parent, symidx,
1105 						symname, try_parent,
1106 						is_function);
1107       if (ret == CTF_ERR)
1108 	ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
1109       return ret;
1110     }
1111   else
1112     return (ctf_set_typed_errno (fp, err));
1113 }
1114 
1115 /* Given a symbol table index, return the type of the function or data object
1116    described by the corresponding entry in the symbol table.  */
1117 ctf_id_t
1118 ctf_lookup_by_symbol (ctf_dict_t *fp, unsigned long symidx)
1119 {
1120   return ctf_lookup_by_sym_or_name (fp, symidx, NULL, 1, -1);
1121 }
1122 
1123 /* Given a symbol name, return the type of the function or data object described
1124    by the corresponding entry in the symbol table.  */
1125 ctf_id_t
1126 ctf_lookup_by_symbol_name (ctf_dict_t *fp, const char *symname)
1127 {
1128   return ctf_lookup_by_sym_or_name (fp, 0, symname, 1, -1);
1129 }
1130 
1131 /* Given a symbol table index, return the info for the function described
1132    by the corresponding entry in the symbol table, which may be a function
1133    symbol or may be a data symbol that happens to be a function pointer.  */
1134 
1135 int
1136 ctf_func_info (ctf_dict_t *fp, unsigned long symidx, ctf_funcinfo_t *fip)
1137 {
1138   ctf_id_t type;
1139 
1140   if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
1141     return -1;					/* errno is set for us.  */
1142 
1143   if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
1144     return (ctf_set_errno (fp, ECTF_NOTFUNC));
1145 
1146   return ctf_func_type_info (fp, type, fip);
1147 }
1148 
1149 /* Given a symbol table index, return the arguments for the function described
1150    by the corresponding entry in the symbol table.  */
1151 
1152 int
1153 ctf_func_args (ctf_dict_t *fp, unsigned long symidx, uint32_t argc,
1154 	       ctf_id_t *argv)
1155 {
1156   ctf_id_t type;
1157 
1158   if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
1159     return -1;					/* errno is set for us.  */
1160 
1161   if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
1162     return (ctf_set_errno (fp, ECTF_NOTFUNC));
1163 
1164   return ctf_func_type_args (fp, type, argc, argv);
1165 }
1166